Back to skill

Security audit

Flickr Claw

Security checks for vulnerabilities and agentic risk

Overview

The skill matches its Flickr-management purpose, but it should be reviewed carefully because it stores Flickr account access tokens locally in plaintext and defaults to write-capable authorization.

Install only if you are comfortable granting a local script access to your Flickr account. Prefer a read-only token for exports and downloads, use write authorization only when editing metadata, avoid delete permission, protect ~/.openclaw from other users and backups, and revoke or rotate Flickr tokens after use. Use a virtual environment and pin dependencies before running it in a sensitive environment.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (4)

T08 · Insecure Dependencies

Warning
Location
SKILL.md:25
Finding

Unpinned Third-Party Dependency Installation

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:25-30; also documented in references/workflow.md:17-22
Vulnerability Type: Supply-chain risk from an unpinned runtime dependency
Risk Level: Medium

Vulnerable Code Snippet:

bash
pip install requests-oauthlib

Technical Analysis

The installation instructions retrieve the latest available version of requests-oauthlib and its transitive dependencies without a version constraint, lock file, or integrity hash. Consequently, installation is not reproducible and the effective code installed by users can change after the Skill has been reviewed.

This does not establish that the current dependency is malicious. However, it creates a supply-chain exposure in which a future compromised release, account takeover, or unexpected dependency change could introduce code that executes during installation or import. Because the script processes Flickr API credentials and OAuth tokens, compromised dependency code would operate in a security-sensitive context.

Attack Path

  1. An attacker compromises a dependency release, maintainer account, package index, or relevant transitive dependency.
  2. The user follows the documented unrestricted pip install requests-oauthlib command.
  3. The package resolver downloads the attacker-controlled or unexpectedly changed release.
  4. Malicious code executes during installation or when requests_oauthlib is imported.
  5. The code can access files and resources available to the Python process, including local Flickr credentials and OAuth token files.

Impact Assessment

Successful exploitation would execute code with the privileges of the user running pip or the Skill. The resulting access could include:

  • Reading Flickr API credentials and OAuth tokens from ~/.openclaw.
  • Accessing generated metadata exports and downloaded photographs.
  • Making Flickr requests with the user's OAuth authority.
  • Reading or m ...[truncated 234 chars]
Remediation
View remediation

Remediation Suggestions

  • Pin requests-oauthlib and all transitive dependencies to reviewed versions.
  • Provide a version-controlled requirements or lock file.
  • Include package hashes and install with pip install --require-hashes.
  • Recommend installation inside a dedicated, non-privileged virtual environment.
  • Use automated dependency scanning and explicitly review dependency updates before changing the lock file.
  • Document the tested Python and dependency versions.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/flickr_skill.py:84
Finding

OAuth Secrets Stored Without Explicit Permission Hardening

Content
View full analysis

Vulnerability Details

File Location: scripts/flickr_skill.py:84-93 and scripts/flickr_skill.py:96-116
Vulnerability Type: Plaintext sensitive-token storage with process-default file permissions
Risk Level: Medium

Vulnerable Code Snippet:

python
def start_auth(req_file: Path, perms: str = 'write'):
    api_key, api_secret = load_creds()
    oauth = OAuth1Session(api_key, client_secret=api_secret, callback_uri='oob')
    tokens = oauth.fetch_request_token(REQUEST_TOKEN_URL)
    req_file.parent.mkdir(parents=True, exist_ok=True)
    req_file.write_text(str(tokens), encoding='utf-8')
    auth_url = oauth.authorization_url(AUTHORIZE_URL, perms=perms)
    print('AUTH_URL:' + auth_url)
    print('REQUEST_TOKEN_FILE:' + str(req_file))
    print('REQUEST_PERMS:' + perms)
python
def finish_auth(req_file: Path, verifier: str, access_file: Path):
    api_key, api_secret = load_creds()
    rt = parse_tokens(req_file)
    oauth = OAuth1Session(
        api_key,
        client_secret=api_secret,
        resource_owner_key=rt['oauth_token'],
        resource_owner_secret=rt['oauth_token_secret'],
        verifier=verifier,
    )
    try:
        tokens = oauth.fetch_access_token(ACCESS_TOKEN_URL)
    except Exception as e:
        fail(
            'Could not redeem Flickr verifier code.\n'
            'Make sure you used the most recent auth URL, approved it, and pasted the verifier exactly.\n'
            f'Details: {e}'
        )
    access_file.parent.mkdir(parents=True, exist_ok=True)
    access_file.write_text(str(tokens), encoding='utf-8')
    print('ACCESS_TOKEN_FILE:' + str(access_file))

Technical Analysis

Request-token and access-token secrets are serialized as plaintext and written with Path.write_text(). The implementation does not explicitly create the files with owner-only permissions, validate the permissions of an existing file, rejec ...[truncated 1788 chars]

Remediation
View remediation

Remediation Suggestions

  • Create the .openclaw directory with owner-only permissions, such as mode 0700 on POSIX systems.
  • Create token files atomically with owner read/write permissions only, such as mode 0600.
  • Check and correct the permissions of existing token files before overwriting them.
  • Reject symbolic links and use safe file-opening primitives that prevent symlink traversal where supported.
  • Validate that custom token paths resolve to an explicitly approved location.
  • Prefer an operating-system credential manager or keyring for long-lived OAuth secrets.
  • Warn or fail when secure file permissions cannot be guaranteed.
  • Delete the temporary request-token file after successful access-token redemption.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/flickr_skill.py:324
Finding

OAuth-Authenticated Download Request Uses an Unvalidated API-Provided URL

Content
View full analysis

Vulnerability Details

File Location: scripts/flickr_skill.py:324-335
Vulnerability Type: Unvalidated outbound destination used with an authenticated OAuth session
Risk Level: Medium

Vulnerable Code Snippet:

python
for i, row in enumerate(rows, start=1):
    pid = row['photo_id']
    sizes = flickr_get(oauth, 'flickr.photos.getSizes', photo_id=pid)['sizes']['size']
    chosen = pick_size(sizes)
    url = chosen['source']
    ext = Path(url).suffix or '.jpg'
    out = out_dir / f"{i:02d}_{pid}{ext}"
    img = oauth.get(url, timeout=120)
    img.raise_for_status()
    out.write_bytes(img.content)

Technical Analysis

The download URL is obtained from the Flickr API response and passed directly to the existing OAuth1Session. The code does not validate the URL scheme or hostname and does not restrict redirects to approved Flickr-controlled image hosts.

Under ordinary operation, Flickr is expected to return legitimate Flickr CDN URLs. Nevertheless, using an authenticated session for an API-provided absolute URL unnecessarily extends trust beyond the fixed Flickr REST endpoint. If the response or redirect chain were manipulated, the client could make an OAuth-related request to an unintended destination. Even where credentials are not reusable due to OAuth signature binding, authorization headers and OAuth metadata may be exposed to the receiving host.

The implementation also lacks response-size and content-type limits, so an unexpected destination or compromised response could return excessively large or non-image content for local storage.

Attack Path

  1. A compromised Flickr API path, manipulated response, malicious intermediary under a broken trust environment, or unexpected upstream behavior supplies a non-Flickr URL in the source field.
  2. The script accepts the URL without checking its scheme or hostname.
  3. OAuth1Session.get() sends a request to that destination and m ...[truncated 890 chars]
Remediation
View remediation

Remediation Suggestions

  • Use a separate unauthenticated requests.Session for image downloads rather than the OAuth-authenticated session.
  • Require the https scheme.
  • Maintain an explicit allowlist of expected Flickr-owned image CDN hostnames.
  • Disable automatic redirects or validate the scheme and hostname of every redirect target.
  • Set a maximum response size and stream downloads in bounded chunks.
  • Validate the response Content-Type against supported image media types.
  • Derive file extensions from an approved content type instead of directly from the remote URL.
  • Abort and report an error if the API returns an unexpected destination.

T05 · Unauthorized Access and Privilege Escalation

Note
Location
scripts/flickr_skill.py:383
Finding

Write-Capable Flickr Authorization Requested by Default

Content
View full analysis

Vulnerability Details

File Location: scripts/flickr_skill.py:84 and scripts/flickr_skill.py:383
Vulnerability Type: Excessive default OAuth privilege
Risk Level: Low

Vulnerable Code Snippet:

python
def start_auth(req_file: Path, perms: str = 'write'):
python
ap.add_argument('--perms', choices=['read', 'write', 'delete'], default='write', help='Requested Flickr OAuth permission level.')

Technical Analysis

The default OAuth permission is write, even though authentication checks, album listing, metadata export, auditing, and image downloads require only read access. Users who start the authorization flow without explicitly selecting a permission therefore receive a token with broader authority than needed for common read-only tasks.

The command also exposes a delete permission choice despite the absence of a deletion feature in the implementation. Although users must explicitly select it, making it available is not necessary for the Skill's declared operations and expands the possible impact of token compromise.

The OAuth transmissions highlighted by the pre-scan are otherwise legitimate: request tokens are fetched from Flickr's fixed HTTPS request-token endpoint, and verifier codes are redeemed at Flickr's fixed HTTPS access-token endpoint. Those exchanges are required for the declared Flickr authentication functionality and do not constitute third-party exfiltration.

Attack Path

  1. A user follows the default --start-auth workflow without specifying --perms read.
  2. The script requests a write-capable Flickr token.
  3. The token is stored locally and later becomes exposed through local compromise, insecure permissions, backup leakage, or another process running as the user.
  4. An attacker uses the unnecessarily privileged token to submit Flickr metadata modifications.
  5. If a user explicitly selected the unsupported delete permission, the compromised authority co ...[truncated 515 chars]
Remediation
View remediation

Remediation Suggestions

  • Change the default permission from write to read.
  • Require users to explicitly request write authorization before invoking metadata-editing operations.
  • Clearly display the requested permission immediately before generating the authorization URL.
  • Remove delete from the accepted choices until a reviewed feature has a legitimate need for it.
  • Consider separate read-only and write-token files to avoid using a privileged token for routine exports and downloads.
  • Document token revocation and rotation procedures.
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
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (14)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 192)May include surrounding context.

md
- `scripts/flickr_skill.py` — Flickr helper with auth, verification, album/recent export, download, and metadata editing support.

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · SKILL.md (reported line 33)May include surrounding context.

md
By default the script stores local state under the current user's home directory in `.openclaw`:

- App credentials: `~/.openclaw/flickr-app-credentials.json`
- Request token: `~/.openclaw/flickr-request-token-manual.txt`
- Access token: `~/.openclaw/flickr-access-token-manual.txt`

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · SKILL.md (reported line 74)May include surrounding context.

md
By default the script stores local state under the current user's home directory in `.openclaw`:

- App credentials: `~/.openclaw/flickr-app-credentials.json`
- Request token: `~/.openclaw/flickr-request-token-manual.txt`
- Access token: `~/.openclaw/flickr-access-token-manual.txt`

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · references/workflow.md (reported line 7)May include surrounding context.

md
By default the script stores local state under the current user's home directory in `.openclaw`:

- App credentials: `~/.openclaw/flickr-app-credentials.json`
- Request token: `~/.openclaw/flickr-request-token-manual.txt`
- Access token: `~/.openclaw/flickr-access-token-manual.txt`

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · references/workflow.md (reported line 60)May include surrounding context.

md
By default the script stores local state under the current user's home directory in `.openclaw`:

- App credentials: `~/.openclaw/flickr-app-credentials.json`
- Request token: `~/.openclaw/flickr-request-token-manual.txt`
- Access token: `~/.openclaw/flickr-access-token-manual.txt`

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/flickr_skill.py (reported line 15)May include surrounding context.

python
By default the script stores local state under the current user's home directory in `.openclaw`:

- App credentials: `~/.openclaw/flickr-app-credentials.json`
- Request token: `~/.openclaw/flickr-request-token-manual.txt`
- Access token: `~/.openclaw/flickr-access-token-manual.txt`

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/flickr_skill.py (reported line 39)May include surrounding context.

python
By default the script stores local state under the current user's home directory in `.openclaw`:

- App credentials: `~/.openclaw/flickr-app-credentials.json`
- Request token: `~/.openclaw/flickr-request-token-manual.txt`
- Access token: `~/.openclaw/flickr-access-token-manual.txt`

Credential Access

High
Category
Privilege Escalation
Confidence
89% confidence
Finding

The documentation explicitly stores an access token in a fixed local plaintext path, enabling persistent reuse of an authenticated session if the file is read by another process or user. Because the token may grant write access, compromise could let an attacker modify photo metadata, tags, descriptions, or otherwise act as the Flickr user through the API.

Content

Scanner excerpt · references/workflow.md (reported line 9)May include surrounding context.

md
- App credentials: `~/.openclaw/flickr-app-credentials.json`
- Request token: `~/.openclaw/flickr-request-token-manual.txt`
- Access token: `~/.openclaw/flickr-access-token-manual.txt`

Credentials file format:

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/flickr_skill.py (reported line 407)May include surrounding context.

python
ap.add_argument('--request-file', default=str(DEFAULT_REQUEST_FILE), help='Path to the saved Flickr request-token file.')
    ap.add_argument('--access-file', default=str(DEFAULT_ACCESS_FILE), help='Path to the saved Flickr access-token file.')
    ap.add_argument('--start-auth', action='store_true', help='Start Flickr OAuth and print an authorization URL.')
    ap.add_argument('--finish-auth', action='store_true', help='Redeem a Flickr verifier code and save the access token.')
    ap.add_argument('--audit', action='store_true', help='Export recent Flickr uploads to CSV.')
    ap.add_argument('--check-auth', action='store_true', help='Verify that the current token works for authenticated Flickr API calls.')
    ap.add_argument('--list-albums', action='store_true', help='List albums/photosets for the authenticated Flickr account.')

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill explicitly instructs users to read and write local credential files, tokens, CSV exports, and downloaded images, but it does not declare any tool scope such as permissions or allowed-tools. That creates a transparency and policy gap: an agent may gain filesystem access broader than the user expects, increasing the risk of unintended access to sensitive local files when handling Flickr credentials and photo data.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The workflow instructs users to store Flickr API credentials and OAuth tokens in predictable plaintext files under the home directory, but it does not warn that these files are sensitive or recommend restrictive file permissions. If another local user, malware, backups, logs, or support tooling accesses these files, an attacker could reuse the tokens or app secret to access or modify the Flickr account.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · references/workflow.md (reported line 37)May include surrounding context.

md
python skills/flickr-claw/scripts/flickr_skill.py --list-albums
python skills/flickr-claw/scripts/flickr_skill.py --album-photos --album-id ALBUM_ID --out ./flickr_album_photos.csv
python skills/flickr-claw/scripts/flickr_skill.py --download-album --album-id ALBUM_ID --out-dir ./flickr-album-downloads
python skills/flickr-claw/scripts/flickr_skill.py --start-auth --perms write
python skills/flickr-claw/scripts/flickr_skill.py --finish-auth --verifier CODE
python skills/flickr-claw/scripts/flickr_skill.py --audit --days 30 --out ./flickr_recent_uploads_audit.csv
python skills/flickr-claw/scripts/flickr_skill.py --download-latest --count 10 --days 30 --out-dir ./flickr-latest-downloads

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/flickr_skill.py (reported line 14)May include surrounding context.

python
REQUEST_TOKEN_URL = 'https://www.flickr.com/services/oauth/request_token'
AUTHORIZE_URL = 'https://www.flickr.com/services/oauth/authorize'
ACCESS_TOKEN_URL = 'https://www.flickr.com/services/oauth/access_token'
REST_URL = 'https://api.flickr.com/services/rest'
CREDS_FILE = Path.home() / '.openclaw' / 'flickr-app-credentials.json'
DEFAULT_REQUEST_FILE = Path.home() / '.openclaw' / 'flickr-request-token-manual.txt'
DEFAULT_ACCESS_FILE = Path.home() / '.openclaw' / 'flickr-access-token-manual.txt'

Session Persistence

Medium
Category
Rogue Agent
Confidence
83% confidence
Finding

The skill persists OAuth request/access tokens and app credentials as plain text under ~/.openclaw without any permission checks or secure storage mechanism. If the local system is shared, backed up insecurely, or other processes can read those files, an attacker could reuse the tokens to access or modify the user’s Flickr account.

Content

Scanner excerpt · scripts/flickr_skill.py (reported line 39)May include surrounding context.

python
if not creds_file.exists():
        fail(
            f'Missing Flickr credentials file: {creds_file}\n'
            'Create ~/.openclaw/flickr-app-credentials.json with api_key and api_secret.'
        )
    try:
        data = json.loads(creds_file.read_text(encoding='utf-8'))

Static analysis

No suspicious patterns detected.