T09 · Insecure Skill Coding Practices
- Location
tools/openapi_auth.py:114- Finding
OAuth credentials are persisted without restrictive file permissions
- Content
View full analysis
Vulnerability Details
File Location:
tools/openapi_auth.py:114-145
Vulnerability Type: Plaintext credential storage with insufficient permission enforcement
Risk Level: MediumVulnerable Code:
python def write_openapi_env( client_id: str, client_secret: str, token_data: Dict[str, object], *, redirect_uri: str = DEFAULT_REDIRECT_URI, path: Optional[Path] = None, ) -> Path: """Write Open API credentials to a local .env file.""" env_path = path or get_openapi_env_path() current = read_openapi_env(env_path) current.update( { "DIDA_OPENAPI_CLIENT_ID": client_id, "DIDA_OPENAPI_CLIENT_SECRET": client_secret, "DIDA_OPENAPI_REDIRECT_URI": redirect_uri, "DIDA_OPENAPI_ACCESS_TOKEN": str(token_data.get("access_token", "")), "DIDA_OPENAPI_REFRESH_TOKEN": str(token_data.get("refresh_token", "")), "DIDA_OPENAPI_TOKEN_TYPE": str(token_data.get("token_type", "")), "DIDA_OPENAPI_SCOPE": str(token_data.get("scope", DEFAULT_SCOPE)), } ) if "expires_in" in token_data: current["DIDA_OPENAPI_EXPIRES_IN"] = str(token_data.get("expires_in", "")) lines = ["# Dida Coach Open API credentials"] for key in sorted(current.keys()): lines.append(f"{key}={current[key]}") env_path.parent.mkdir(parents=True, exist_ok=True) env_path.write_text("\n".join(lines) + "\n", encoding="utf-8") return env_pathTechnical Analysis
The function stores the OAuth client secret, access token, and refresh token as plaintext in
~/.dida-coach/dida-openapi.env. It writes the file usingPath.write_text()without explicitly creating it with owner-only permissions or correcting the permissions of an existing file.The resulting permissions depend on the process umask. With a common umask such as
022, a newly created cr ...[truncated 1666 chars]- Remediation
View remediation
Remediation Suggestions
- Create the credential file atomically with owner-only mode
0600, rather than relying on the process umask. - Explicitly apply
chmod(0o600)after creation and when updating an existing file. - Ensure the parent credential directory is restricted to mode
0700. - Use a temporary file in the same directory, set restrictive permissions before writing, flush and synchronize it, and atomically replace the destination to prevent partial writes.
- Prefer an operating-system credential store or keychain for client secrets and refresh tokens.
- Store only credentials required for subsequent operations and avoid retaining the client secret if it is unnecessary after authorization.
- Document that the credential file contains sensitive values and must never be committed, shared, or included in diagnostic output.
- Create the credential file atomically with owner-only mode
