Back to skill

Security audit

Codex Multi Subscription Auth Fallbacks

Security checks for vulnerabilities and agentic risk

Overview

The skill is coherent and local-only, but it copies OAuth login tokens and leaves credential backups on disk, so users should review it before installing.

Install only if you are comfortable letting this skill copy Codex OAuth access and refresh tokens into OpenClaw's local auth profile store. Before running it, use a non-production account if possible, keep auth-profiles.json and all .bak files out of chats, logs, screenshots, backups, and version control, check that the files are readable only by your user, and delete unneeded timestamped auth backups after confirming the import worked. Enable the optional cron job only if you want recurring background model switching.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/codex-add-profile.sh:24
Finding
Persistent Plaintext Backups of OAuth Credentials## Vulnerability Details **File Location**: `scripts/codex-add-profile.sh`, lines 24-27, 54-69, and 178-184 **Vulnerability Type**: Sensitive credential storage in persistent plaintext backups **Risk Level**: Medium ### Vulnerable Code ```bash CODEX_AUTH="$HOME/.codex/auth.json" CODEX_BACKUP="${CODEX_AUTH}.bak-$(date +%s)" OPENCLAW_BACKUP="${OPENCLAW_AUTH}.bak-$(date +%s)" # Step 1: Back up both files echo "==> Backing up existing auth files" if [ -f "$CODEX_AUTH" ]; then cp "$CODEX_AUTH" "$CODEX_BACKUP" # Verify backup succeeded if [ ! -f "$CODEX_BACKUP" ]; then echo "Error: Failed to create backup at $CODEX_BACKUP" exit 1 fi echo " Codex CLI: $CODEX_BACKUP" fi if [ -f "$OPENCLAW_AUTH" ]; then cp "$OPENCLAW_AUTH" "$OPENCLAW_BACKUP" if [ ! -f "$OPENCLAW_BACKUP" ]; then echo "Error: Failed to create backup at $OPENCLAW_BACKUP" exit 1 fi echo " OpenClaw: $OPENCLAW_BACKUP" fi echo "" echo "==> Done! Profile openai-codex:$PROFILE_NAME added." echo " OpenClaw backup: $OPENCLAW_BACKUP" echo " Codex backup: $CODEX_BACKUP" ``` ### Technical Analysis The script copies two authentication files into timestamped backup files: - `~/.codex/auth.json`, which may contain live Codex OAuth access and refresh tokens. - `~/.openclaw/agents/main/agent/auth-profiles.json`, which contains imported OAuth credentials for one or more profiles. These backups are retained after a successful execution. No cleanup, expiration, rotation, encryption, or explicit restrictive permission enforcement is applied. Every execution can therefore create additional credential-bearing files that remain usable until their tokens expire or are revoked. The use of `cp` does not independently enforce a secure mode such as `0600`; resulting protection depends on source permissions, platform behavior, the user's `umask`, and parent-directory access controls. Timestamp-based n ...[truncated 1720 chars]
Remediation
## Remediation Suggestions 1. Create backup files with explicit owner-only permissions: ```bash umask 077 install -m 600 "$CODEX_AUTH" "$CODEX_BACKUP" install -m 600 "$OPENCLAW_AUTH" "$OPENCLAW_BACKUP" ``` 2. Use securely generated, collision-resistant temporary names rather than timestamp-only names: ```bash CODEX_BACKUP="$(mktemp "${CODEX_AUTH}.bak.XXXXXXXX")" OPENCLAW_BACKUP="$(mktemp "${OPENCLAW_AUTH}.bak.XXXXXXXX")" ``` 3. Delete temporary credential backups after successful restoration and profile import: ```bash rm -f -- "$CODEX_BACKUP" "$OPENCLAW_BACKUP" ``` 4. If rollback backups must be retained, require explicit user opt-in and implement a bounded retention policy. Store retained backups in an owner-only directory, enforce mode `0600`, and clearly instruct users how and when to remove them. 5. Validate that the authentication directories are owned by the current user and are not group- or world-writable before creating sensitive files. 6. Preserve the existing trap-based restoration behavior, but extend cleanup handling so temporary backups are securely removed only after restoration has succeeded. Avoid deleting the sole valid backup when restoration fails. 7. Recommend revoking and reauthorizing affected OAuth sessions if historical backup permissions may have allowed unauthorized access.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (7)

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding
The code does support one portion of the description: adding a new Codex OAuth profile via device flow and importing it into OpenClaw. However, the declared purpose prominently includes broader capabilities—multi-provider auth setup, OAuth fallback profiles, automatic model switching, and cron-job-based switching when a provider hits cooldown—that are not present in this code chunk. The script is narrowly focused on interactively adding a single OpenAI Codex auth profile by backing up auth files, forcing a fresh Codex login, extracting tokens, updating OpenClaw's auth-profiles.json, and restoring the original Codex CLI auth. This makes the description materially broader than the actual behavior.

Credential Access

High
Category
Privilege Escalation
Content
Each Codex profile contains:
- `type`: `"oauth"`
- `provider`: `"openai-codex"`
- `access`: JWT access token (auto-populated by the add-profile script)
- `refresh`: Refresh token (auto-populated)
- `expires`: Token expiry in ms (parsed from JWT)
- `accountId`: OpenAI account ID (parsed from JWT)
Confidence
94% confidence
Finding
The skill is designed to extract OAuth access and refresh tokens from one local auth store and copy them into another file. Even if intended for legitimate failover, handling long-lived bearer credentials in plaintext local files materially increases credential exposure risk through file disclosure, backups, logs, or downstream tool compromise; the context makes this especially sensitive because refresh tokens can enable persistent account access.

Credential Access

High
Category
Privilege Escalation
Content
};
if (tokens.account_id) profileEntry.accountId = tokens.account_id;

// Calculate expiry from access token JWT (exp claim)
try {
  const parts = tokens.access_token.split(".");
  const payload = JSON.parse(Buffer.from(parts[1], "base64url").toString());
Confidence
84% confidence
Finding
The script reads OAuth access and refresh tokens from ~/.codex/auth.json and persists them into ~/.openclaw/agents/main/agent/auth-profiles.json, creating another long-lived copy of highly sensitive credentials. This increases credential exposure because the tokens are duplicated on disk, handled in plaintext JSON, and backed up/restored without any permission hardening or secure storage controls.

Lp3

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding
The skill explicitly declares access to sensitive auth files and relies on local environment/runtime capabilities, but it does not define a restrictive tool scope such as permissions or allowed-tools. In an agent setting, missing scope boundaries increases the blast radius if the skill or a referenced script is modified, because the agent may be able to read environment data or invoke capabilities beyond what users expect.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
- **Tokens stay local.** No tokens are sent to any external endpoint. The script reads tokens from the local Codex CLI auth file and writes them to the local OpenClaw auth-profiles file.
- **Backups are always created.** Both files are backed up with timestamps before any modification. If login fails or the script is interrupted, a trap handler restores the original Codex CLI auth automatically.
- **Interactive confirmation.** The script prompts for confirmation before clearing the Codex CLI auth file, so you can abort if needed.
- **No elevated privileges.** The script runs as your user and does not require sudo or any special permissions.
- **Back up manually first.** Despite the automatic backups, it is recommended to manually back up `~/.codex/auth.json` and your OpenClaw configs before running, especially on first use.
- **Test with a non-production account.** For initial testing, consider using a throwaway or non-production OpenAI account.
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The documentation shows a schema for storing live OAuth credential material, including access tokens, refresh tokens, expiry data, and account identifiers, but does not explicitly warn that these values are sensitive secrets that must never be committed, logged, or shared. In a skill specifically about multi-account auth failover and automation, this omission increases the chance that users will copy real token-bearing files into chats, repos, bug reports, or automation state, leading to account compromise or unauthorized API use.

Session Persistence

Medium
Category
Rogue Agent
Content
cp "$CODEX_AUTH" "$CODEX_BACKUP"
  # Verify backup succeeded
  if [ ! -f "$CODEX_BACKUP" ]; then
    echo "Error: Failed to create backup at $CODEX_BACKUP"
    exit 1
  fi
  echo "    Codex CLI:  $CODEX_BACKUP"
Confidence
79% confidence
Finding
The script creates timestamped backup files of both Codex and OpenClaw authentication material, which can leave valid session tokens recoverable on disk indefinitely. Even though the stated purpose is safety and recovery, these backups expand the attack surface because any local user, malware, backup system, or accidental file disclosure could expose still-valid credentials.

Static analysis

No suspicious patterns detected.