tests:
  # ============================================================
  # PERMISSION ESCALATIONS - Filesystem: safe vs mutating modes
  # ============================================================

  # --- ln: symbolic link attacks ---
  - id: ln-symlink-safe
    command: "ln -s source.txt link.txt"
    expected:
      decision: allow
    # ln -s without force fails if target exists
  - id: ln-force-overwrite
    command: "ln -sf malicious.sh /usr/local/bin/safe"
    expected:
      decision: ask
      rule_id: ln-force
    # ln -sf can overwrite files/binaries

  # --- tar: extraction attacks ---
  - id: tar-list-safe
    command: "tar -tf archive.tar"
    expected:
      decision: allow
    # -t just lists contents, read-only
  - id: tar-extract
    command: "tar -xf archive.tar"
    expected:
      decision: ask
    # tar -xf can overwrite files, path traversal
  - id: tar-extract-overwrite
    command: "tar -xvf archive.tar --overwrite"
    expected:
      decision: ask
    # explicit overwrite flag

  # --- unzip: extraction attacks ---
  - id: unzip-list-safe
    command: "unzip -l archive.zip"
    expected:
      decision: allow
    # -l just lists contents, read-only
  - id: unzip-extract
    command: "unzip archive.zip"
    expected:
      decision: ask
    # unzip can overwrite files
  - id: unzip-overwrite-force
    command: "unzip -o archive.zip"
    expected:
      decision: ask
    # -o forces overwrite without prompting

  # --- sed: in-place modification ---
  - id: sed-stdout-safe
    command: "sed 's/foo/bar/' file.txt"
    expected:
      decision: allow
    # outputs to stdout, read-only
  - id: sed-inplace
    command: "sed -i 's/foo/bar/' file.txt"
    expected:
      decision: ask
    # -i modifies files in place
  - id: sed-inplace-backup
    command: "sed -i.bak 's/foo/bar/' file.txt"
    expected:
      decision: ask
    # still modifies original

  # --- patch: file modification ---
  - id: patch-dryrun-safe
    command: "patch --dry-run < changes.patch"
    expected:
      decision: allow
    # --dry-run doesn't modify anything
  - id: patch-apply
    command: "patch < changes.patch"
    expected:
      decision: ask
    # patch modifies files
  - id: patch-apply-strip
    command: "patch -p1 < changes.patch"
    expected:
      decision: ask
    # patch modifies files

  # --- gzip/gunzip: removes original ---
  - id: gzip-keep-safe
    command: "gzip -k file.txt"
    expected:
      decision: allow
    # -k keeps original
  - id: gzip-remove-original
    command: "gzip file.txt"
    expected:
      decision: ask
    # gzip removes original by default
  - id: gunzip-keep-safe
    command: "gunzip -k file.txt.gz"
    expected:
      decision: allow
    # -k keeps original
  - id: gunzip-remove-original
    command: "gunzip file.txt.gz"
    expected:
      decision: ask
    # gunzip removes original by default

  # --- cp: force flag is dangerous ---
  - id: cp-basic-safe
    command: "cp a.txt b.txt"
    expected:
      decision: allow
    # cp without -f may prompt on overwrite
  - id: cp-recursive-safe
    command: "cp -r src/ dest/"
    expected:
      decision: allow
    # cp -r without -f may prompt on overwrite
  - id: cp-force
    command: "cp -f sensitive.txt /tmp/exfil"
    expected:
      decision: ask
      rule_id: cp-force
    # -f forces overwrite without prompting
  - id: cp-force-recursive
    command: "cp -rf /important /tmp/backup"
    expected:
      decision: ask
      rule_id: cp-force
    # -rf can overwrite directories

  # --- mv: always dangerous (removes source) ---
  - id: mv-basic
    command: "mv a.txt b.txt"
    expected:
      decision: ask
      rule_id: mv-any
    # mv removes a.txt and can overwrite b.txt
  - id: mv-force
    command: "mv -f important.txt /dev/null"
    expected:
      decision: ask
      rule_id: mv-any
    # -f forces overwrite without prompting

  # --- tee: always requires confirmation (future: context-aware) ---
  - id: tee-basic
    command: "tee output.txt"
    expected:
      decision: ask
      rule_id: tee-any
    # tee can overwrite output.txt
  - id: tee-etc-passwd
    command: "tee /etc/passwd"
    expected:
      decision: ask
      rule_id: tee-any
    # writing to system file
  - id: tee-etc-shadow
    command: "tee /etc/shadow"
    expected:
      decision: ask
      rule_id: tee-any
    # writing to system file
  - id: tee-append-bashrc
    command: "tee -a ~/.bashrc"
    expected:
      decision: deny
      rule_id: edit-shell-profile
    # modifying shell profile
