Skip to content
1Claw Academy
Curriculum/Foundations2 minBeginner · Lesson 9 of 13

Lab: watch a secret cross into a process you did not write

Lab

Put a credential in the environment, spawn something, and see what it inherits.

The previous lesson put a secret in an environment variable and called it better than a file, which it is. This lab is about the cost that comes with it, and it is a cost people are consistently surprised by.

  1. 1

    Set a credential in the environment and spawn a child process that you did not write.

    bash
    cat > /tmp/inherit.py <<'EOF'
    import os, subprocess
    
    print("parent has API_TOKEN:", bool(os.environ.get("API_TOKEN")))
    
    child = subprocess.run(
        ["python3", "-c",
         "import os; print('child sees:', os.environ.get('API_TOKEN'))"],
        capture_output=True, text=True)
    print(child.stdout.strip())
    EOF
    API_TOKEN=sk-live-INHERITED python3 /tmp/inherit.py
  2. 2

    The child never asked for it and received it anyway.

    text
    parent has API_TOKEN: True
    child sees: sk-live-INHERITED
  3. 3

    Clean up.

    bash
    rm /tmp/inherit.py

Environment variables are inherited by default. That is the whole mechanism, and it is why the environment is convenient: you set it once and everything downstream can use it. The consequence is that everything downstream can use it.

  • Every subprocess inherits your whole environment: a build step, a linter, a test runner, an npm postinstall script, a crash reporter.
  • So does anything they spawn, all the way down. There is no depth limit and no audit trail.
  • Anything that serialises the environment into a bug report ships the credential with it, which is how secrets reach error trackers without any log line naming them.
Tip

Pass an explicit env to a subprocess rather than inheriting the whole one. In Python that is subprocess.run(..., env={...}); most languages have the equivalent, and almost nobody uses it.

Watch out

This is also the honest limit of 1claw env run. It keeps the value off disk, which is a real improvement, and the process it starts still hands the value to everything it spawns.

Check your understanding

3 questions
1

Why did the child process see the token?

2

How deep does that inheritance go?

3

What is the practical mitigation?