T09 · Insecure Skill Coding Practices
- Location
scripts/codex_auth.py:109- Finding
OAuth secrets are stored in predictably named temporary files without enforced restrictive permissions
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This OAuth helper is mostly purpose-aligned, but it needs review because it handles long-lived login tokens using unsafe temporary files and can restart the local gateway in the background.
Install only if you are comfortable with this skill writing OpenAI OAuth access and refresh tokens into local OpenClaw auth files and potentially restarting the gateway. Avoid queue mode until token staging is moved out of /tmp, permissions are forced to 0600, queued payloads are deleted after use, state validation rejects missing state, and callback URLs are not passed through shell command arguments.
scripts/codex_auth.py:109OAuth secrets are stored in predictably named temporary files without enforced restrictive permissions
scripts/codex_auth.py:186Atomic replacement invalidates auth-profile locking and can weaken credential-file permissions
scripts/codex_auth.py:324OAuth state verification fails open when callback state is omitted
scripts/codex_auth.py:286Sensitive OAuth callback credentials are accepted through command-line arguments
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
## Denied operations
- No remote shell execution (`curl|bash`, `wget|sh`).
- No `sudo`, SSH, package manager, or system mutation actions.
- No disclosure of full callback query params, access tokens, or refresh tokens.
The skill is presented as a deprecated shim that should redirect users elsewhere, but the content describes a fully active OAuth flow that exchanges tokens, writes auth data, and can restart the gateway. This mismatch is dangerous because users and automated governance may treat it as low-risk or inactive while it still performs privileged operations on sensitive credentials and local service state.
The skill can queue a background apply job that writes tokens to disk and controls the gateway lifecycle, which is far more powerful than its stated deprecated shim purpose suggests. In context, this mismatch is dangerous because users or callers may reasonably expect an auth helper, not a tool that creates persistence artifacts and asynchronously changes service state.
The skill declares no explicit tool scope or permission boundaries, yet the documented behavior includes shell execution, network access, and reads/writes of sensitive auth state. In an agent ecosystem, missing permission declarations weakens reviewability and enforcement, making it easier for a seemingly simple skill to perform higher-risk actions than operators expect.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
TOKEN_URL = "https://auth.openai.com/oauth/token"
REDIRECT_URI = "http://localhost:1455/auth/callback"
SCOPE = "openid profile email offline_access"
JWT_CLAIM_PATH = "https://api.openai.com/auth"
OPENCLAW_CONFIG_PATH = str(Path.home() / ".openclaw" / "openclaw.json")
BACKUP_DIR = "/tmp/openclaw/safety-backups"
APPLY_STATUS_PATH = "/tmp/openclaw/codex-auth-apply-last.json"
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
def run_cmd(cmd):
return subprocess.run(cmd, capture_output=True, text=True)
def apply_with_gateway_restart(payload_path, auth_path):
This deprecated compatibility/auth script performs active system reconfiguration, modifies persistent auth/config files, and stops/starts the gateway service. Those capabilities exceed a minimal auth-flow shim and increase the chance of unauthorized persistence, outages, or unsafe rollback behavior if the script is triggered unexpectedly or with manipulated inputs.
The apply path stops and restarts the gateway service as part of credential application without an immediate user confirmation in the action-performing code path. In a deprecated shim, undisclosed service interruption is risky because it can disrupt workloads and be abused as an availability-impacting action under the guise of authentication.
The queued apply path writes OAuth access and refresh tokens into a payload file under /tmp/openclaw before launching a background job. Temporary directories are a poor place for sensitive secrets because they may be exposed to other local users/processes, persist longer than intended, and are not accompanied by clear user disclosure in this path.
The code spawns a detached background process that later applies configuration and restarts the gateway, using attacker-influenced inputs such as --auth-path and a payload file in /tmp. Although it does not use a shell, background execution reduces visibility and control, and in this deprecated auth shim context it expands the blast radius beyond simple authentication.
args.auth_path,
]
with open("/tmp/openclaw/codex-auth-apply.log", "a", encoding="utf-8") as lf:
subprocess.Popen(cmd, stdout=lf, stderr=lf, stdin=subprocess.DEVNULL)
print(json.dumps({
"ok": True,
"profile": profile_id,
The script persists access and refresh tokens to the auth profile file without an explicit disclosure or consent step in this code path. Persisting long-lived credentials is expected for OAuth tooling, but doing so silently in a deprecated shim increases surprise and reduces the user's ability to assess local secret-handling risk.
The comment says the non-queued path performs an immediate write with 'no restart,' but the same branch calls ensure_profile_declared_in_config and then reports restart_required and a config note telling the user to restart the gateway. That documentation understates the operational impact of the path and contradicts the emitted result semantics.
No suspicious patterns detected.