Skip to content

Commit 2d72ba0

Browse files
sunny-seclaude
andcommitted
fix(security): use isolated temp directory in spm.sh scripts
F-014 / DEVA11Y-483 — Concurrent spm.sh instances shared CWD (CWE-362), causing cleanup trap to delete sibling's Package.swift. Use mktemp -d for an isolated working directory per invocation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 0428b32 commit 2d72ba0

3 files changed

Lines changed: 36 additions & 18 deletions

File tree

scripts/bash/spm.sh

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
#!/usr/bin/env bash -il
22

3-
[ -f "${PWD}/Package.swift" ]
4-
PACKAGE_EXISTS="$?"
3+
ORIGINAL_DIR="${PWD}"
4+
HAS_EXISTING_PACKAGE=0
5+
[ -f "${PWD}/Package.swift" ] && HAS_EXISTING_PACKAGE=1
56
GIT_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
67
SCRIPT_PATH=$(realpath --relative-to="$GIT_ROOT" "$0" 2>/dev/null || realpath "$0")
78
SUBCOMMAND="$1"
@@ -41,19 +42,23 @@ EOF
4142
a11y_scan() {
4243
# Ensure Package.swift is removed on exit (acts like a finally block)
4344
cleanup() {
44-
if [ $PACKAGE_EXISTS -eq 0 ]; then
45+
if [ $HAS_EXISTING_PACKAGE -eq 1 ]; then
4546
return
4647
fi
47-
rm -f -- "${PWD}/Package.swift" "${PWD}/Package.resolved"
48+
if [ -n "$WORK_DIR" ] && [ -d "$WORK_DIR" ]; then
49+
rm -rf -- "$WORK_DIR"
50+
fi
4851
}
4952
trap cleanup EXIT
5053

5154
setup() {
52-
if [ $PACKAGE_EXISTS -eq 0 ]; then
55+
if [ $HAS_EXISTING_PACKAGE -eq 1 ]; then
56+
WORK_DIR="$ORIGINAL_DIR"
5357
return
5458
fi
5559

56-
cat > Package.swift <<EOF
60+
WORK_DIR=$(mktemp -d)
61+
cat > "$WORK_DIR/Package.swift" <<EOF
5762
// swift-tools-version: 5.9
5863
import PackageDescription
5964
@@ -71,6 +76,7 @@ EOF
7176
if [[ -z "$EXTRA_ARGS" ]]; then
7277
EXTRA_ARGS="--include **/*.swift --include **/*.xib --include **/*.storyboard"
7378
fi
79+
cd "$WORK_DIR"
7480
env -i HOME="$HOME" \
7581
XCODE_VERSION_ACTUAL="$XCODE_VERSION_ACTUAL"\
7682
BROWSERSTACK_USERNAME="$BROWSERSTACK_USERNAME"\

scripts/fish/spm.sh

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@ export BROWSERSTACK_USERNAME=$($fish_bin -lic 'echo $BROWSERSTACK_USERNAME' | ta
1313
export BROWSERSTACK_ACCESS_KEY=$($fish_bin -lic 'echo $BROWSERSTACK_ACCESS_KEY' | tail -n 1)
1414

1515
# Don't change anything after this, same as the bash equivalent
16-
[ -f "${PWD}/Package.swift" ]
17-
PACKAGE_EXISTS="$?"
16+
ORIGINAL_DIR="${PWD}"
17+
HAS_EXISTING_PACKAGE=0
18+
[ -f "${PWD}/Package.swift" ] && HAS_EXISTING_PACKAGE=1
1819
GIT_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
1920
SCRIPT_PATH=$(realpath --relative-to="$GIT_ROOT" "$0" 2>/dev/null || realpath "$0")
2021
SUBCOMMAND="$1"
@@ -54,19 +55,23 @@ EOF
5455
a11y_scan() {
5556
# Ensure Package.swift is removed on exit (acts like a finally block)
5657
cleanup() {
57-
if [ $PACKAGE_EXISTS -eq 0 ]; then
58+
if [ $HAS_EXISTING_PACKAGE -eq 1 ]; then
5859
return
5960
fi
60-
rm -f -- "${PWD}/Package.swift" "${PWD}/Package.resolved"
61+
if [ -n "$WORK_DIR" ] && [ -d "$WORK_DIR" ]; then
62+
rm -rf -- "$WORK_DIR"
63+
fi
6164
}
6265
trap cleanup EXIT
6366

6467
setup() {
65-
if [ $PACKAGE_EXISTS -eq 0 ]; then
68+
if [ $HAS_EXISTING_PACKAGE -eq 1 ]; then
69+
WORK_DIR="$ORIGINAL_DIR"
6670
return
6771
fi
6872

69-
cat > Package.swift <<EOF
73+
WORK_DIR=$(mktemp -d)
74+
cat > "$WORK_DIR/Package.swift" <<EOF
7075
// swift-tools-version: 5.9
7176
import PackageDescription
7277
@@ -84,6 +89,7 @@ EOF
8489
if [[ -z "$EXTRA_ARGS" ]]; then
8590
EXTRA_ARGS="--include **/*.swift --include **/*.xib --include **/*.storyboard"
8691
fi
92+
cd "$WORK_DIR"
8793
env -i HOME="$HOME" \
8894
XCODE_VERSION_ACTUAL="$XCODE_VERSION_ACTUAL"\
8995
BROWSERSTACK_USERNAME="$BROWSERSTACK_USERNAME"\

scripts/zsh/spm.sh

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@ export BROWSERSTACK_USERNAME=$($zsh_bin -lic 'echo $BROWSERSTACK_USERNAME' | tai
1212
export BROWSERSTACK_ACCESS_KEY=$($zsh_bin -lic 'echo $BROWSERSTACK_ACCESS_KEY' | tail -n 1)
1313

1414
# Don't change anything after this, same as the bash equivalent
15-
[ -f "${PWD}/Package.swift" ]
16-
PACKAGE_EXISTS="$?"
15+
ORIGINAL_DIR="${PWD}"
16+
HAS_EXISTING_PACKAGE=0
17+
[ -f "${PWD}/Package.swift" ] && HAS_EXISTING_PACKAGE=1
1718
GIT_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
1819
SCRIPT_PATH=$(realpath --relative-to="$GIT_ROOT" "$0" 2>/dev/null || realpath "$0")
1920
SUBCOMMAND="$1"
@@ -53,19 +54,23 @@ EOF
5354
a11y_scan() {
5455
# Ensure Package.swift is removed on exit (acts like a finally block)
5556
cleanup() {
56-
if [ $PACKAGE_EXISTS -eq 0 ]; then
57+
if [ $HAS_EXISTING_PACKAGE -eq 1 ]; then
5758
return
5859
fi
59-
rm -f -- "${PWD}/Package.swift" "${PWD}/Package.resolved"
60+
if [ -n "$WORK_DIR" ] && [ -d "$WORK_DIR" ]; then
61+
rm -rf -- "$WORK_DIR"
62+
fi
6063
}
6164
trap cleanup EXIT
6265

6366
setup() {
64-
if [ $PACKAGE_EXISTS -eq 0 ]; then
67+
if [ $HAS_EXISTING_PACKAGE -eq 1 ]; then
68+
WORK_DIR="$ORIGINAL_DIR"
6569
return
6670
fi
6771

68-
cat > Package.swift <<EOF
72+
WORK_DIR=$(mktemp -d)
73+
cat > "$WORK_DIR/Package.swift" <<EOF
6974
// swift-tools-version: 5.9
7075
import PackageDescription
7176
@@ -83,6 +88,7 @@ EOF
8388
if [[ -z "$EXTRA_ARGS" ]]; then
8489
EXTRA_ARGS="--include **/*.swift --include **/*.xib --include **/*.storyboard"
8590
fi
91+
cd "$WORK_DIR"
8692
env -i HOME="$HOME" \
8793
XCODE_VERSION_ACTUAL="$XCODE_VERSION_ACTUAL"\
8894
BROWSERSTACK_USERNAME="$BROWSERSTACK_USERNAME"\

0 commit comments

Comments
 (0)