diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 00000000..d407607a --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,67 @@ +# GitHub Copilot Shell Scripting (sh) Review Instructions + +## 🎯 Overall Goal + +Your role is to act as a rigorous yet helpful senior engineer, reviewing Shell script code (`.sh` files). Ensure the code exhibits the highest levels of robustness, security, and portability. +The review must focus on risks unique to Shell scripting, such as proper quoting, robust error handling, and the secure execution of external commands. + +## 📝 Required Output Format + +Please adhere to the previous format: organize the feedback into a single, structured report, using the three-level marking system: + +1. **🔴 Critical Issues (Must Fix Before Merge)** +2. **🟡 Suggestions (Improvements to Consider)** +3. **✅ Good Practices (Points to Commend)** + +--- + +## 🔍 Focus Areas and Rules for Shell + +### 1. Robustness and Error Handling + +* **Shebang:** Check that the script starts with the correct Shebang, must be "#!/usr/bin/env sh". +* **Startup Options:** **(🔴 Critical)** Enforce the use of the following combination at the start of the script for safety and robustness: + * `set -e`: Exit immediately if a command exits with a non-zero status. + * `set -u`: Treat unset variables as an error and exit. + * `set -o pipefail`: Ensure the whole pipeline fails if any command in the pipe fails. +* **Exit Codes:** Ensure functions and the main script use `exit 0` for success and a non-zero exit code upon failure. +* **Temporary Files:** Check for the use of `mktemp` when creating temporary files to prevent race conditions and security risks. + +### 2. Security and Quoting + +* **Variable Quoting:** **(🔴 Critical)** Check that all variable expansions (like `$VAR` and `$(COMMAND)`) are properly enclosed in **double quotes** (i.e., `"$VAR"` and `"$(COMMAND)"`) to prevent **Word Splitting** and **Globbing**. +* **Hardcoded Secrets:** **(🔴 Critical)** Find and flag any hardcoded passwords, keys, tokens, or authentication details. +* **Untrusted Input:** Verify that all user input, command-line arguments (`$1`, `$2`, etc.), or environment variables are rigorously validated and sanitized before use. +* **Avoid `eval`:** Warn against and suggest alternatives to using `eval`, as it can lead to arbitrary code execution. + +### 3. Readability and Maintainability + +* **Function Usage:** Recommend wrapping complex or reusable logic within clearly named functions. +* **Local Variables:** Check that variables inside functions are declared using the `local` keyword to avoid unintentionally modifying global state. +* **Naming Convention:** Variable names should use uppercase letters and underscores (e.g., `MY_VARIABLE`), or follow established project conventions. +* **Test Conditions:** Encourage the use of Bash's **double brackets `[[ ... ]]`** for conditional tests, as it is generally safer and more powerful (e.g., supports pattern matching and avoids Word Splitting) than single brackets `[ ... ]`. +* **Command Substitution:** Encourage using `$(command)` over backticks `` `command` `` for command substitution, as it is easier to nest and improves readability. + +### 4. External Commands and Environment + +* **`for` Loops:** Warn against patterns like `for i in $(cat file)` or `for i in $(ls)` and recommend the more robust `while IFS= read -r line` pattern for safely processing file contents or filenames that might contain spaces. +* **Use existing acme.sh functions whenever possible.** For example: do not use `tr '[:upper:]' '[:lower:]'`, use `_lower_case` instead. +* **Do not use `head -n`.** Use the `_head_n()` function instead. +* **Do not use `curl` or `wget`.** Use the `_post()` and `_get()` functions instead. + +--- + +### 5. Review Rules for Files Under `dnsapi/`: + +* **Each file must contain a `{filename}_add` function** for adding DNS TXT records. It should use `_readaccountconf_mutable` to read the API key and `_saveaccountconf_mutable` to save it. Do not use `_saveaccountconf` or `_readaccountconf`. + + +## ❌ Things to Avoid + +* Do not comment on purely stylistic issues like spacing or indentation, which should be handled by tools like ShellCheck or Prettier. +* Do not be overly verbose unless a significant issue is found. Keep feedback concise and actionable. + + + + + diff --git a/.github/workflows/DragonFlyBSD.yml b/.github/workflows/DragonFlyBSD.yml index f3a85920..9d4d8acb 100644 --- a/.github/workflows/DragonFlyBSD.yml +++ b/.github/workflows/DragonFlyBSD.yml @@ -46,7 +46,7 @@ jobs: ACME_USE_WGET: ${{ matrix.ACME_USE_WGET }} steps: - uses: actions/checkout@v6 - - uses: vmactions/cf-tunnel@v0 + - uses: anyvm-org/cf-tunnel@v0 id: tunnel with: protocol: http @@ -67,7 +67,7 @@ jobs: run: | cd ../acmetest \ && ./letest.sh - - name: onError + - name: DebugOnError if: ${{ failure() }} run: | echo "See how to debug in VM:" diff --git a/.github/workflows/FreeBSD.yml b/.github/workflows/FreeBSD.yml index e9ccf7ac..09b544f6 100644 --- a/.github/workflows/FreeBSD.yml +++ b/.github/workflows/FreeBSD.yml @@ -52,7 +52,7 @@ jobs: ACME_USE_WGET: ${{ matrix.ACME_USE_WGET }} steps: - uses: actions/checkout@v6 - - uses: vmactions/cf-tunnel@v0 + - uses: anyvm-org/cf-tunnel@v0 id: tunnel with: protocol: http @@ -72,7 +72,7 @@ jobs: run: | cd ../acmetest \ && ./letest.sh - - name: onError + - name: DebugOnError if: ${{ failure() }} run: | echo "See how to debug in VM:" diff --git a/.github/workflows/Haiku.yml b/.github/workflows/Haiku.yml index bfbde398..4324545e 100644 --- a/.github/workflows/Haiku.yml +++ b/.github/workflows/Haiku.yml @@ -53,7 +53,7 @@ jobs: ACME_USE_WGET: ${{ matrix.ACME_USE_WGET }} steps: - uses: actions/checkout@v6 - - uses: vmactions/cf-tunnel@v0 + - uses: anyvm-org/cf-tunnel@v0 id: tunnel with: protocol: http @@ -75,7 +75,7 @@ jobs: run: | cd ../acmetest \ && ./letest.sh - - name: onError + - name: DebugOnError if: ${{ failure() }} run: | echo "See how to debug in VM:" diff --git a/.github/workflows/Linux.yml b/.github/workflows/Linux.yml index 9f3d3f38..17462033 100644 --- a/.github/workflows/Linux.yml +++ b/.github/workflows/Linux.yml @@ -34,6 +34,13 @@ jobs: TEST_ACME_Server: "LetsEncrypt.org_test" steps: - uses: actions/checkout@v6 + - uses: anyvm-org/cf-tunnel@v0 + id: tunnel + with: + protocol: http + port: 80 + - name: Set envs + run: echo "TestingDomain=${{steps.tunnel.outputs.server}}" >> $GITHUB_ENV - name: Clone acmetest run: | cd .. \ diff --git a/.github/workflows/MacOS.yml b/.github/workflows/MacOS.yml index 21793c3e..3869b504 100644 --- a/.github/workflows/MacOS.yml +++ b/.github/workflows/MacOS.yml @@ -47,6 +47,13 @@ jobs: - uses: actions/checkout@v6 - name: Install tools run: brew install socat + - uses: anyvm-org/cf-tunnel@v0 + id: tunnel + with: + protocol: http + port: 80 + - name: Set envs + run: echo "TestingDomain=${{steps.tunnel.outputs.server}}" >> $GITHUB_ENV - name: Clone acmetest run: | cd .. \ diff --git a/.github/workflows/NetBSD.yml b/.github/workflows/NetBSD.yml index e8107d91..4021cd7e 100644 --- a/.github/workflows/NetBSD.yml +++ b/.github/workflows/NetBSD.yml @@ -46,7 +46,7 @@ jobs: ACME_USE_WGET: ${{ matrix.ACME_USE_WGET }} steps: - uses: actions/checkout@v6 - - uses: vmactions/cf-tunnel@v0 + - uses: anyvm-org/cf-tunnel@v0 id: tunnel with: protocol: http @@ -67,7 +67,7 @@ jobs: run: | cd ../acmetest \ && ./letest.sh - - name: onError + - name: DebugOnError if: ${{ failure() }} run: | echo "See how to debug in VM:" diff --git a/.github/workflows/Omnios.yml b/.github/workflows/Omnios.yml index a166e26b..a156800c 100644 --- a/.github/workflows/Omnios.yml +++ b/.github/workflows/Omnios.yml @@ -52,7 +52,7 @@ jobs: ACME_USE_WGET: ${{ matrix.ACME_USE_WGET }} steps: - uses: actions/checkout@v6 - - uses: vmactions/cf-tunnel@v0 + - uses: anyvm-org/cf-tunnel@v0 id: tunnel with: protocol: http @@ -71,7 +71,7 @@ jobs: run: | cd ../acmetest \ && ./letest.sh - - name: onError + - name: DebugOnError if: ${{ failure() }} run: | echo "See how to debug in VM:" diff --git a/.github/workflows/OpenBSD.yml b/.github/workflows/OpenBSD.yml index b34c795b..8a91cd2e 100644 --- a/.github/workflows/OpenBSD.yml +++ b/.github/workflows/OpenBSD.yml @@ -52,7 +52,7 @@ jobs: ACME_USE_WGET: ${{ matrix.ACME_USE_WGET }} steps: - uses: actions/checkout@v6 - - uses: vmactions/cf-tunnel@v0 + - uses: anyvm-org/cf-tunnel@v0 id: tunnel with: protocol: http @@ -72,7 +72,7 @@ jobs: run: | cd ../acmetest \ && ./letest.sh - - name: onError + - name: DebugOnError if: ${{ failure() }} run: | echo "See how to debug in VM:" diff --git a/.github/workflows/OpenIndiana.yml b/.github/workflows/OpenIndiana.yml index 6447911b..dca29741 100644 --- a/.github/workflows/OpenIndiana.yml +++ b/.github/workflows/OpenIndiana.yml @@ -52,7 +52,7 @@ jobs: ACME_USE_WGET: ${{ matrix.ACME_USE_WGET }} steps: - uses: actions/checkout@v6 - - uses: vmactions/cf-tunnel@v0 + - uses: anyvm-org/cf-tunnel@v0 id: tunnel with: protocol: http @@ -71,7 +71,7 @@ jobs: run: | cd ../acmetest \ && ./letest.sh - - name: onError + - name: DebugOnError if: ${{ failure() }} run: | echo "See how to debug in VM:" diff --git a/.github/workflows/Solaris.yml b/.github/workflows/Solaris.yml index f5ce713b..397469b5 100644 --- a/.github/workflows/Solaris.yml +++ b/.github/workflows/Solaris.yml @@ -52,7 +52,7 @@ jobs: ACME_USE_WGET: ${{ matrix.ACME_USE_WGET }} steps: - uses: actions/checkout@v6 - - uses: vmactions/cf-tunnel@v0 + - uses: anyvm-org/cf-tunnel@v0 id: tunnel with: protocol: http @@ -73,7 +73,7 @@ jobs: run: | cd ../acmetest \ && ./letest.sh - - name: onError + - name: DebugOnError if: ${{ failure() }} run: | echo "See how to debug in VM:" diff --git a/.github/workflows/Windows.yml b/.github/workflows/Windows.yml index 4c195917..c628ff5b 100644 --- a/.github/workflows/Windows.yml +++ b/.github/workflows/Windows.yml @@ -67,6 +67,13 @@ jobs: shell: cmd run: | echo "PATH=%PATH%" + - uses: anyvm-org/cf-tunnel@v0 + id: tunnel + with: + protocol: http + port: 80 + - name: Set envs + run: echo "TestingDomain=${{steps.tunnel.outputs.server}}" >> $GITHUB_ENV - name: Clone acmetest shell: cmd run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ diff --git a/dnsapi/dns_me.sh b/dnsapi/dns_me.sh index 43c903cd..163fe8db 100644 --- a/dnsapi/dns_me.sh +++ b/dnsapi/dns_me.sh @@ -53,6 +53,8 @@ dns_me_add() { _info "Added" #todo: check if the record takes effect return 0 + elif printf -- "%s" "$response" | grep -q "already exists"; then + _info "Record already exists, skipping." else _err "Add txt record error." return 1 diff --git a/dnsapi/dns_technitium.sh b/dnsapi/dns_technitium.sh index 7bc0dd48..fbe44606 100755 --- a/dnsapi/dns_technitium.sh +++ b/dnsapi/dns_technitium.sh @@ -6,6 +6,7 @@ Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_technitium Options: Technitium_Server Server Address Technitium_Token API Token + Technitium_Expiry_Ttl Number of seconds before DNS server auto-deletes the acme record Issues: github.com/acmesh-official/acme.sh/issues/6116 Author: Henning Reich ' @@ -15,7 +16,10 @@ dns_technitium_add() { _Technitium_account fulldomain=$1 txtvalue=$2 - response="$(_get "$Technitium_Server/api/zones/records/add?token=$Technitium_Token&domain=$fulldomain&type=TXT&text=${txtvalue}")" + expiryTtl=${Technitium_Expirty_Ttl:-$(_readaccountconf_mutable Technitium_Expiry_Ttl)} + expiryTtl=${expiryTtl:-0} + + response="$(_get "$Technitium_Server/api/zones/records/add?token=$Technitium_Token&domain=$fulldomain&type=TXT&text=${txtvalue}&expiryTtl=$expiryTtl")" if _contains "$response" '"status":"ok"'; then return 0 fi @@ -28,6 +32,14 @@ dns_technitium_rm() { _Technitium_account fulldomain=$1 txtvalue=$2 + expiryTtl=${Technitium_Expirty_Ttl:-$(_readaccountconf_mutable Technitium_Expiry_Ttl)} + expiryTtl=${expiryTtl:-0} + + if [ "$expiryTtl" -ne 0 ]; then + _info "DNS record is configured to be auto-removed after $expiryTtl seconds. Remove operation is bypassed." + return 0 + fi + response="$(_get "$Technitium_Server/api/zones/records/delete?token=$Technitium_Token&domain=$fulldomain&type=TXT&text=${txtvalue}")" if _contains "$response" '"status":"ok"'; then return 0