Back to skill

Security audit

Clawcast - Cast Ethereum Wallet for Agents

Security checks for vulnerabilities and agentic risk

Overview

This wallet skill is purpose-aligned, but it handles crypto secrets in ways that could expose funds and makes broad local/system changes.

Review carefully before installing. Do not use this with valuable wallets unless the secret-handling flow is changed: mnemonics, private keys, and keystore passwords should not be entered into chat or stored in plaintext files. Prefer a hardware wallet or external signer, verify any Foundry installation separately, and avoid allowing the skill to run sudo/package-manager commands or automatic balance checks unless you understand the exposure.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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 (5)

T03 · Remote Payload Retrieval and Execution

Error
Location
scripts/01_install_cast.sh:14
Finding

Unverified Remote Installer Is Piped Directly Into a Shell

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:29
Finding

Skill Instructions Encourage Collection of Mnemonics and Private Keys Through the Agent

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/03_password.sh:25
Finding

Keystore Password Is Always Retained in a Plaintext File

Content
View full analysis
"${PASSWORD_FILE}" chmod 600 "${PASSWORD_FILE}" || true ok "Password saved to ${PASSWORD_FILE}" ``` ### Technical Analysis The keystore password is unconditionally written to `~/.agent-wallet/pw.txt`, and the state is forcibly set to indicate that the password should be saved. The user is not offered a non-persistent mode. File permissions of `0600` prevent access by other ordinary operating-system users, but they do not protect against malicious processes running under the same account, compromised Agent tools, backup systems, or accidental disclosure. Because the encrypted keystore and its decryption password are stored under the same user account, theft of both files permits unattended signing and substantially defeats the purpose of encrypting the keystore at rest. ### Attack Path 1. The user completes wallet onboarding. 2. The script stores the encrypted keystore and plaintext password on the same account. 3. A malicious or compromised process running as that user reads `~/.agent-wallet/pw.txt` and `~/.agent-wallet/keystore.json`. 4. The process decrypts the keystore or supplies both files to `cast`. 5. It signs and broadcasts transactions without another password prompt. ### Impact Assessment A same-user compromise or disclosure of the wallet directory can lead to unauthorized transaction signing and theft of all assets controlled by the keystore. The exposure persists until the password file is removed, and changing only the file permissions does not protect against same-user access. ]]>
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/02_wallet.sh:179
Finding

Mnemonic and Private Key Material Is Written to Plaintext Files

Content
View full analysis
"${MNEMONIC_FILE}" chmod 600 "${MNEMONIC_FILE}" || true ok "Recovery words saved to ${MNEMONIC_FILE}" cleanup_note="$(schedule_mnemonic_file_cleanup "${MNEMONIC_FILE}")" warn "Mnemonic file will be deleted in ~1 hour (${cleanup_note})." else warn "Could not automatically capture the mnemonic from cast; please record it securely now." fi fi if ! [[ "$PRIVATE_KEY" =~ ^0x[0-9a-fA-F]{64}$ ]]; then err "Private key format invalid." exit 1 fi printf "%s" "${PRIVATE_KEY}" > "${PK_TMP}" chmod 600 "${PK_TMP}" || true ``` The cleanup function can leave the mnemonic on disk: ```bash if ! ensure_at_available; then warn "Mnemonic file ${target} won't auto-delete (no 'at'). Please remove it after ~1 hour." return fi ``` ### Technical Analysis The script stores both the mnemonic and private key as unencrypted plaintext. Although `umask 077` and mode `0600` reduce cross-user access, the files remain readable by every process operating as the wallet owner. The mnemonic is intentionally retained for approximately one hour, while the private key remains until the next onboarding step succeeds. If the process crashes, the user interrupts onboarding, keystore creation fails, or scheduling through `at` is unavailable, secrets may remain on disk indefinitely. Copies may also persist in snapshots, backups, filesystem journals, or forensic storage even after ordinary deletion. ### Attack Path 1. The user creates or imports wallet material. 2. The script writes the mnemonic and private key into files under `~/.agent-wallet`. 3. Onboarding is interrupte ...[truncated 610 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/02_wallet.sh:43
Finding

Wallet Setup Attempts Privileged Package Installation for Optional Cleanup

Content
View full analysis
/tmp/at-install.log 2>&1"; then warn "Failed to install 'at' with sudo; mnemonic cleanup will be manual." return 1 fi else if ! sh -c "$installer > /tmp/at-install.log 2>&1"; then warn "Failed to install 'at'; mnemonic cleanup will be manual." return 1 fi fi hash -r if has_cmd at; then ok "Installed 'at' so mnemonic cleanup can be scheduled." return 0 fi warn "Installation succeeded but 'at' still unavailable; cleanup will be manual." return 1 } schedule_mnemonic_file_cleanup() { local target="$1" if ! ensure_at_available; then warn "Mnemonic file ${target} won't auto-delete (no 'at'). Please remove it after ~1 hour." return fi local job_output rc set +e job_output="$(printf 'rm -f -- %q\n' "$target" | at now + 1 hour 2>&1)" ``` ### Technical Analysis Wallet generation does not require the `at` package. Nevertheless, the setup flow attempts to install it through `sudo` solely to schedule deletion of a plaintext mnemonic. This crosses the least-privilege boundary and modifies the host package set without a dedicated, informed approval step. The function also creates a scheduled job that survives the immediate script process. The observed job only removes the mnemonic and is not a backdoor, but installing a system package and creating scheduler state are br ...[truncated 1157 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
Findings (33)

Ssd 3

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

This section directs the agent to persist extremely sensitive wallet material and related metadata: saving generated mnemonic words to disk, storing the keystore password in a local helper file, keeping wallet state in persistent files, and logging transaction mentions. In a wallet-management context this is especially dangerous because compromise of these local artifacts can lead to wallet theft, long-term surveillance of financial activity, and recovery of funds by anyone obtaining the seed phrase or password file.

Content

No source excerpt is available for this finding.

External Script Fetching

High
Category
Supply Chain
Confidence
99% confidence
Finding

This finding is valid because the script fetches and executes an external installer from the network, creating a direct supply-chain execution path. Given the skill's purpose is managing EVM wallets and transactions, compromise of the installed tooling could lead to credential theft, transaction manipulation, or installation of backdoored binaries in the user's shell environment.

Content

Scanner excerpt · scripts/01_install_cast.sh (reported line 15)May include surrounding context.

sh
exit 0
fi
if ! has_cmd curl; then
  err "curl is required but not found. Install curl and re-run."
  exit 1
fi
warn "cast not found. Installing Foundry..."

Chaining Abuse

High
Category
Tool Misuse
Confidence
99% confidence
Finding

Piping curl output directly into bash is a classic unsafe chaining pattern because it combines retrieval and execution into one step, leaving no opportunity for validation or integrity checks. In this wallet-oriented context, any attacker controlling the response could achieve arbitrary code execution and potentially persist in the user's shell startup files or exfiltrate wallet-related secrets.

Content

Scanner excerpt · scripts/01_install_cast.sh (reported line 19)May include surrounding context.

sh
exit 1
fi
warn "cast not found. Installing Foundry..."
curl -L https://foundry.paradigm.xyz | bash
enable_strict_path
if ! has_cmd foundryup; then
  for p in "${HOME}/.bashrc" "${HOME}/.zshrc" "${HOME}/.profile"; do

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding

The skill invokes shell scripts, reads local state, and writes sensitive wallet data, but declares no explicit tool scope or permission boundaries. In an agent environment, this increases the chance the skill is executed with broader-than-necessary filesystem and shell access, which is risky given it handles secrets and persistent state.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
87% confidence
Finding

The onboarding scripts are designed to create or import keys, encrypt keystores, and persist network/token state across sessions. Persistence itself is expected for wallets, but the issue is that the skill normalizes long-lived local storage of highly sensitive state without clearly constraining where and how it is protected.

Content

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

md
## Scripts

- **Step scripts** — `scripts/01_install_cast.sh`..`06_finish.sh` cover the onboarding flow described in the README: install Foundry/cast, create or import a key, encrypt the keystore, choose network/RPC/tokens (sourced from the JSON assets), and show the resulting address and balance. Run them in order when the user requests onboarding. Each script already prompts for the necessary inputs (mnemonic/private key, password, RPC URL, token details), so relaying the same questions to the user and then running the next script is the recommended approach.
- **Wallet health check** — `scripts/check_wallet.sh` inspects the shared state and reports whether a keystore/address pair already exists; it returns success (0) when a wallet is present and 1 otherwise.
- **Network status** — `scripts/show_network.sh` prints the active network name, chainId, and RPC URL from `~/.agent-wallet/state.env`, or warns if the configuration is incomplete.
- **Wallet removal** — `scripts/remove_wallet.sh` safely deletes the keystore, password stash, and metadata from `~/.agent-wallet/state.env` after an explicit confirmation.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

The skill text describes token-step behavior that conflicts with the earlier script model, including direct JSON mutation of token metadata. In security-sensitive wallet workflows, inconsistent documentation can cause an agent to modify reference assets unexpectedly, potentially corrupting trusted network/token data or persisting user-provided values into shared configuration.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
90% confidence
Finding

The skill instructs the agent to automatically run wallet readiness checks, reveal saved address and keystore path, and query balances/network status without first asking the user. This can expose sensitive local wallet metadata and trigger outbound RPC requests that reveal the user's address and IP-linked activity to third-party nodes.

Content

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

md
Always ask the user, right before running each script, exactly the question that script itself will ask (password, network choice, etc.). Do not invent or fill in answers on their behalf—only use the information they explicitly provide. This keeps onboarding faithful to what they chose and avoids pushing the scripts forward with made-up data.

1. **Start with targeted help if stuck.** Pipe `cast --help` through `grep` (e.g., `cast --help | grep balance`) to zero in on the relevant subcommand and avoid scrolling the entire manual; this saves tokens and keeps the answer focused before you proceed or explain anything.
2. **Automatic readiness check.** Run `scripts/check_wallet.sh` automatically each session; do not ask the user to trigger it. If it detects an existing wallet, immediately display the saved address/keystore path and proceed to show the balance/network status (see next step) so the user sees “wallet ready” without extra probes.
3. **Show wallet + network status.** When `check_wallet` finds a wallet, run `scripts/show_network.sh` and query the balance (e.g., `cast balance <ADDRESS> --rpc-url <RPC_URL> --ether`) so the user sees the current native balance, network name, chainId, and RPC URL without being prompted to check anything manually.
4. **Onboarding flow** (automatic when no wallet exists). If the readiness check exits with 1, walk through the scripted steps in order, mirroring their prompts and explicitly asking the user for every required piece of information before running the next script. After the key-material step finishes, share the derived address immediately so the user sees it before we ask them for anything in step 3:
   1. Installation — explain that the script will ensure Foundry/cast is installed so every mentioned `cast` command works before proceeding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
97% confidence
Finding

This instruction covers collecting mnemonics or private keys and persisting a generated mnemonic to a local file for later deletion. In a wallet skill, handling key material is inherently high risk, and writing seed phrases to disk substantially increases the chance of compromise from malware, backups, shell history, or other local users/processes.

Content

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

md
3. **Show wallet + network status.** When `check_wallet` finds a wallet, run `scripts/show_network.sh` and query the balance (e.g., `cast balance <ADDRESS> --rpc-url <RPC_URL> --ether`) so the user sees the current native balance, network name, chainId, and RPC URL without being prompted to check anything manually.
4. **Onboarding flow** (automatic when no wallet exists). If the readiness check exits with 1, walk through the scripted steps in order, mirroring their prompts and explicitly asking the user for every required piece of information before running the next script. After the key-material step finishes, share the derived address immediately so the user sees it before we ask them for anything in step 3:
   1. Installation — explain that the script will ensure Foundry/cast is installed so every mentioned `cast` command works before proceeding.
   2. Key material — before running the wallet step, ask whether they want to create a new hot keypair, import a 12/24-word MetaMask-compatible mnemonic (`m/44'/60'/0'/0/0`), or import a private key. Collect the chosen secret, confirm the resulting address right after the step finishes, and tell the user that address before moving on. When generating a new keypair, capture the mnemonic displayed by `cast wallet new`, save it to `~/.agent-wallet/mnemonic-words-<timestamp>.txt`, and tell the user the exact path plus the fact that a job (via `at now + 1 hour` if available or a background `sleep` fallback) will delete that file after 60 minutes so the seed phrase does not linger.
   3. Password — only ask for the keystore password once (there is no confirmation prompt, no save/remember question, and the account name is forced to “agent”). The script saves that password to the local helper file and uses it when creating the keystore, so nothing else is needed from the user for this step.
   4. Network — read aloud the default network list derived from `assets/evm-networks.json`, ask which numbered network they want, and note 
...[truncated 25 chars]

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
86% confidence
Finding

The skill authorizes automatic onboarding steps and post-step actions around wallet creation/import, address disclosure, network selection, and balance retrieval with limited confirmation boundaries. In a financial context, autonomous progression through sensitive setup can cause accidental secret handling, unintended persistence, or unwanted network interactions before the user has reviewed each action.

Content

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

md
4. **Onboarding flow** (automatic when no wallet exists). If the readiness check exits with 1, walk through the scripted steps in order, mirroring their prompts and explicitly asking the user for every required piece of information before running the next script. After the key-material step finishes, share the derived address immediately so the user sees it before we ask them for anything in step 3:
   1. Installation — explain that the script will ensure Foundry/cast is installed so every mentioned `cast` command works before proceeding.
   2. Key material — before running the wallet step, ask whether they want to create a new hot keypair, import a 12/24-word MetaMask-compatible mnemonic (`m/44'/60'/0'/0/0`), or import a private key. Collect the chosen secret, confirm the resulting address right after the step finishes, and tell the user that address before moving on. When generating a new keypair, capture the mnemonic displayed by `cast wallet new`, save it to `~/.agent-wallet/mnemonic-words-<timestamp>.txt`, and tell the user the exact path plus the fact that a job (via `at now + 1 hour` if available or a background `sleep` fallback) will delete that file after 60 minutes so the seed phrase does not linger.
   3. Password — only ask for the keystore password once (there is no confirmation prompt, no save/remember question, and the account name is forced to “agent”). The script saves that password to the local helper file and uses it when creating the keystore, so nothing else is needed from the user for this step.
   4. Network — read aloud the default network list derived from `assets/evm-networks.json`, ask which numbered network they want, and note that the script now auto-selects the first RPC URL from that entry (it saves the matching `CHAIN_ID`/`ETH_RPC_URL` and then just shows the RPC so the user can see which endpoint is being used).
   5. Tokens — the script now prints the token table derived from `assets/evm-network-tokens.json` so it appears directly i
...[truncated 25 chars]

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill instructs the agent to write wallet addresses, transaction hashes, and descriptions to a local log without warning or consent. Even if not secret like a private key, this is sensitive financial metadata that can reveal identity, holdings, counterparties, and transaction patterns.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% 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 · assets/evm-network-tokens.json (reported line 229)May include surrounding context.

json
"name": "Avalanche C-Chain",
      "chainId": 43114,
      "rpcUrls": [
        "https://api.avax.network/ext/bc/C/rpc"
      ],
      "links": {
        "docs": "https://build.avax.network/docs/primary-network",

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% 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 · assets/evm-networks.json (reported line 88)May include surrounding context.

json
"name": "Avalanche C-Chain",
      "chainId": 43114,
      "rpcUrls": [
        "https://api.avax.network/ext/bc/C/rpc"
      ],
      "links": {
        "docs": "https://build.avax.network/docs/primary-network",

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/00_lib.sh (reported line 93)May include surrounding context.

sh
ensure_app_dir() {
  mkdir -p "${APP_DIR}"
  chmod 700 "${APP_DIR}" || true
}

state_init() {

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The function derives a raw private key directly from a mnemonic phrase and returns it to the caller without any warning, consent gate, or minimization of secret exposure. In a wallet-management skill, this is especially sensitive because it normalizes handling the most dangerous credential material in plaintext, increasing the chance of accidental logging, persistence, shell history leakage, or downstream misuse.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The script downloads code from a remote URL and immediately pipes it to bash, which executes whatever the server returns at runtime with no integrity verification, review step, or confirmation prompt. In a wallet-management skill, this is especially dangerous because a compromised upstream host, TLS interception, or malicious update could install trojaned tooling that steals private keys, tampers with transactions, or alters RPC/network behavior.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The script expands its scope from wallet management into host package management by attempting to install at via apt/sudo. In a wallet-handling context, invoking privileged system changes increases trust requirements and attack surface, and could surprise users or be abused if the execution environment or package sources are compromised.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
95% confidence
Finding

The script invokes sudo sh -c to install a package, which causes privileged shell execution from a wallet onboarding flow. Even though the immediate command is fixed, any unnecessary privilege escalation in a secret-handling skill materially raises risk if the script, environment, or package supply chain is tampered with.

Content

Scanner excerpt · scripts/02_wallet.sh (reported line 57)May include surrounding context.

sh
return 1
  fi
  if [[ -x "/usr/bin/sudo" ]]; then
    if ! sudo sh -c "$installer > /tmp/at-install.log 2>&1"; then
      warn "Failed to install 'at' with sudo; mnemonic cleanup will be manual."
      return 1
    fi

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The script handles highly sensitive wallet secrets and writes both the mnemonic and private key to plaintext files on disk, even if permissions are restricted. In a wallet-management skill, this is especially dangerous because any local compromise, backup sync, crash dump, or later file exposure can directly lead to irreversible theft of funds.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The script writes the wallet keystore password directly to a plaintext file at ${APP_DIR}/pw.txt, then later uses that file to unlock the keystore. Although file permissions are restricted with umask 077 and chmod 600, any local compromise of the user account, backups, logs, sync tools, or accidental file disclosure exposes the password and defeats much of the benefit of encrypting the keystore.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/00_lib.sh (reported line 103)May include surrounding context.

sh
state_set "SAVE_PASSWORD" "y"
umask 077
printf "%s" "$PW" > "${PASSWORD_FILE}"
chmod 600 "${PASSWORD_FILE}" || true
ok "Password saved to ${PASSWORD_FILE}"
acct_name="agent"
state_set "KEYSTORE_NAME" "${acct_name}"

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/00_lib.sh (reported line 130)May include surrounding context.

sh
state_set "SAVE_PASSWORD" "y"
umask 077
printf "%s" "$PW" > "${PASSWORD_FILE}"
chmod 600 "${PASSWORD_FILE}" || true
ok "Password saved to ${PASSWORD_FILE}"
acct_name="agent"
state_set "KEYSTORE_NAME" "${acct_name}"

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/00_lib.sh (reported line 140)May include surrounding context.

sh
state_set "SAVE_PASSWORD" "y"
umask 077
printf "%s" "$PW" > "${PASSWORD_FILE}"
chmod 600 "${PASSWORD_FILE}" || true
ok "Password saved to ${PASSWORD_FILE}"
acct_name="agent"
state_set "KEYSTORE_NAME" "${acct_name}"

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/00_lib.sh (reported line 158)May include surrounding context.

sh
state_set "SAVE_PASSWORD" "y"
umask 077
printf "%s" "$PW" > "${PASSWORD_FILE}"
chmod 600 "${PASSWORD_FILE}" || true
ok "Password saved to ${PASSWORD_FILE}"
acct_name="agent"
state_set "KEYSTORE_NAME" "${acct_name}"

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/00_lib.sh (reported line 200)May include surrounding context.

sh
state_set "SAVE_PASSWORD" "y"
umask 077
printf "%s" "$PW" > "${PASSWORD_FILE}"
chmod 600 "${PASSWORD_FILE}" || true
ok "Password saved to ${PASSWORD_FILE}"
acct_name="agent"
state_set "KEYSTORE_NAME" "${acct_name}"

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/02_wallet.sh (reported line 183)May include surrounding context.

sh
state_set "SAVE_PASSWORD" "y"
umask 077
printf "%s" "$PW" > "${PASSWORD_FILE}"
chmod 600 "${PASSWORD_FILE}" || true
ok "Password saved to ${PASSWORD_FILE}"
acct_name="agent"
state_set "KEYSTORE_NAME" "${acct_name}"

Static analysis

No suspicious patterns detected.