Secrets, Credentials, Environment Isolation, and Security Hygiene: Guided Hands-On Workflow
Build a disposable fake-secret pipeline: source from environment, wrap as Secret, enforce a target guard, verify masking, demonstrate one intentional fake disclosure, scan artifacts, and clean process state.
Learning objectives
- Create a Secret-typed variable from an environment variable without putting the value in source.
- Pass Secret to a typed custom keyword while keeping domain result evidence non-sensitive.
- Use an allowlist before any credential-bearing action.
- Demonstrate and detect an unsafe plaintext boundary with a fake sentinel.
- Prove environment and artifact cleanup independently.
Current compatibility baseline — verified 2026-08-31.
Robot Framework 7.4.2 is the stable course baseline
and requires Python 3.8+. Secret variables and
robot.api.types.Secret are new in Robot Framework 7.4.
Secret values are masked in Robot's own argument/return
representations, but they are not encrypted, and
code can access the real value through .value. The
mandatory labs use only a deliberately fake value, a synthetic
allowlisted target, local files under an isolated temporary/project
directory, and Robot Framework core/standard libraries. No real
account, browser, API, database, SSH service, Pabot, CI provider,
container runtime, secret manager, paid platform, or production
system is required. Robot Framework 7.5b1 is prerelease and is not
required.
1. Scenario and ownership
Create rf23-secret-lab/ with one Robot suite, one small
Python library, one artifact scanner, and isolated output
directories. The token is deliberately fake and never leaves the
local machine. The safe run should contain no raw sentinel in Robot
result artifacts. A separate diagnostic run intentionally accesses
.value and must be detected by the scanner.
rf23-secret-lab/
├── libraries/
│ └── secret_guard.py
├── tools/
│ └── scan_artifacts.py
├── suites/
│ └── security.robot
└── evidence/
├── safe/
└── unsafe/
2. Setup and preflight
mkdir -p rf23-secret-lab/libraries rf23-secret-lab/tools rf23-secret-lab/suites rf23-secret-lab/evidence
cd rf23-secret-lab
python -m venv .venv
# Bash/zsh
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install robotframework==7.4.2
export RF23_FAKE_TOKEN='RF23_FAKE_ONLY_7z9q'
python --version
python -m robot --version
python -c "import os; print('token present:', 'RF23_FAKE_TOKEN' in os.environ)"
New-Item -ItemType Directory -Force rf23-secret-lab/libraries,rf23-secret-lab/tools,rf23-secret-lab/suites,rf23-secret-lab/evidence | Out-Null
Set-Location rf23-secret-lab
py -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install robotframework==7.4.2
$env:RF23_FAKE_TOKEN='RF23_FAKE_ONLY_7z9q'
python --version
python -m robot --version
python -c "import os; print('token present:', 'RF23_FAKE_TOKEN' in os.environ)"
Do not run echo $RF23_FAKE_TOKEN or its PowerShell
equivalent. Presence is enough for preflight. The virtual
environment owns the Robot installation; your shell owns the parent
environment variable.
3. Build the Secret-aware library and target guard
# libraries/secret_guard.py
from robot.api import Failure, logger
from robot.api.deco import keyword, library
from robot.api.types import Secret
_ALLOWED_TARGETS = {"local-synthetic"}
@library(scope="TEST")
class SecretGuard:
@keyword
def assert_allowed_target(self, target: str) -> None:
if target not in _ALLOWED_TARGETS:
raise Failure(f"Target {target!r} is not allowlisted.")
logger.info(f"Target guard passed for {target!r}.")
@keyword
def use_fake_secret_safely(self, token: Secret) -> str:
# Real code would hand token.value only to the minimum required client API.
if not token.value.startswith("RF23_FAKE_ONLY_"):
raise Failure("Lab accepts only the documented fake-token prefix.")
logger.info(f"Received Secret object {token}; raw value was not logged.")
return "synthetic-operation-accepted"
@keyword
def unsafe_unwrap_for_demonstration(self, token: Secret) -> str:
# INTENTIONALLY UNSAFE. Use only with the fake lab value.
return token.value
SecretGuard uses TEST scope so no credential-related
instance state survives between tests. The “unsafe” keyword exists
only to create a controlled failure demonstration. It must never be
reused as a production helper.
4. Create the Robot suite
*** Settings ***
Library ../libraries/secret_guard.py
Library OperatingSystem
Library Process
Library Collections
*** Variables ***
${TARGET} local-synthetic
${TOKEN: Secret} %{RF23_FAKE_TOKEN}
*** Test Cases ***
Safe Secret Path
Assert Allowed Target ${TARGET}
${status}= Use Fake Secret Safely ${TOKEN}
Should Be Equal ${status} synthetic-operation-accepted
Log Safe path completed without unwrapping the token.
Secret-Aware Environment Operation
Set Environment Variable RF23_CHILD_TOKEN ${TOKEN}
${python}= Evaluate sys.executable modules=sys
&{env}= Create Dictionary RF23_CHILD_TOKEN=${TOKEN}
${result}= Run Process ${python} -c
... import os; print('present' if os.getenv('RF23_CHILD_TOKEN') else 'missing')
... env=${env}
Should Be Equal ${result.stdout} present
Remove Environment Variable RF23_CHILD_TOKEN
Unsafe Fake Disclosure
[Tags] unsafe-demo
Assert Allowed Target ${TARGET}
${plaintext}= Unsafe Unwrap For Demonstration ${TOKEN}
Log INTENTIONAL FAKE LEAK: ${plaintext}
The first test never asks for .value. The second
demonstrates a separate boundary: Robot can keep the parent
configuration representation redacted while a child process still
receives the real value. The third test intentionally creates
plaintext and is excluded from normal execution.
5. Safe run and before/after evidence
python -m robot --exclude unsafe-demo --outputdir evidence/safe suites/security.robot
# Expected: PASS. Inspect artifacts without printing the token.
find evidence/safe -maxdepth 1 -type f -print 2>/dev/null || true
python -m robot --exclude unsafe-demo --outputdir evidence/safe suites/security.robot
Get-ChildItem evidence/safe -File | Select-Object Name,Length
Expected evidence includes PASS status, target-guard messages, the
word <secret> or otherwise masked argument
rendering where appropriate, child-process result
present, and no raw fake sentinel. Notice that proving
the child saw the value does not require printing the value itself.
6. Scan artifacts without passing the secret on the command line
# tools/scan_artifacts.py
import os
import pathlib
import sys
root = pathlib.Path(sys.argv[1])
needle = os.environ["RF23_FAKE_TOKEN"].encode()
hits = []
for path in root.rglob("*"):
if path.is_file():
try:
data = path.read_bytes()
except OSError:
continue
if needle in data:
hits.append(str(path.relative_to(root)))
if hits:
print("FAKE secret sentinel found in:")
for hit in hits:
print(f" - {hit}")
raise SystemExit(1)
print("No raw fake secret sentinel found.")
python tools/scan_artifacts.py evidence/safe
# Expected exit code: 0
For real secrets, content scanning needs care: providing the credential itself to a scanner can create another disclosure path. Production secret scanners commonly look for patterns, known leaked identifiers, or repository history rather than requiring operators to copy a live credential into a command.
7. Controlled unsafe demonstration
FAKE VALUE ONLY. This test intentionally writes the fake token into Robot evidence. Do not substitute a real credential.
python -m robot --include unsafe-demo --outputdir evidence/unsafe suites/security.robot
python tools/scan_artifacts.py evidence/unsafe
# Expected scanner exit code: 1 and one or more artifact filenames.
The Robot test itself can pass while the security scan fails. That is intentional: functional correctness and evidence hygiene are independent quality gates.
8. Cleanup and rollback
# Preserve evidence until you have finished the comparison. Then:
unset RF23_FAKE_TOKEN
rm -rf evidence/safe evidence/unsafe
python -c "import os; print('token present:', 'RF23_FAKE_TOKEN' in os.environ)"
Remove-Item Env:RF23_FAKE_TOKEN -ErrorAction SilentlyContinue
Remove-Item evidence/safe,evidence/unsafe -Recurse -Force -ErrorAction SilentlyContinue
python -c "import os; print('token present:', 'RF23_FAKE_TOKEN' in os.environ)"
Robot's Remove Environment Variable can only mutate the
Robot process environment. It cannot remove an environment variable
from the parent shell that launched Robot. That distinction is part
of environment isolation.
9. Challenge: choose the right layer
You need a real API token in CI. The API library is known to dump request headers at DEBUG. Choose the design change: (a) rely on Robot Secret and enable DEBUG, (b) disable/avoid sensitive transport logging and pass the value only to the minimum client call, while using non-secret request IDs as evidence, or (c) log the token hash to prove identity.
Answer target: choose (b). Robot masking does not control third-party request dumps, and deterministic hashes can still become sensitive metadata for low-entropy secrets.
10. Summary and bridge
The safe lab proves three separate controls: target allowlisting, Secret-aware Robot data flow, and artifact scanning. The unsafe run proves that unwrapping a Secret crosses a hard boundary. Lesson 3 turns those observations into design choices for CI stores, environment variables, external clients, identity scope, and retention.
Knowledge check
Why does the safe artifact scan run after the Robot test?
A PASS status proves functional behavior, not absence of credential material. Artifact hygiene needs an independent verification step.
Why is RF23_CHILD_TOKEN removed inside Robot and
the parent RF23_FAKE_TOKEN removed in the
shell?
They exist in different process environments. A child cannot rewrite the parent shell environment.
The unsafe disclosure test passes. Is that a green pipeline?
No. The separate scanner must fail because security/evidence policy is independent of functional status.
Why use a dedicated fake-token prefix in the custom library?
It prevents accidentally substituting a real credential into a demonstration keyword whose purpose includes deliberate disclosure.
References and version anchors
- Robot Framework 7.4.2 User Guide — Secret variables — creation, masking, command-line and programmatic use, and limitations.
- Robot Framework 7.4.2 User Guide — Secret type — typed library arguments and disclosure boundary.
- Robot Framework 7.4.2 OperatingSystem — environment/file operations including Secret-aware arguments.
- Robot Framework 7.4.2 Process — process arguments/environment and result evidence.
- Robot Framework PyPI — stable and prerelease version status and Python requirement.
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0
Send only Ethereum/ERC-20 compatible assets to this
address.