diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..aff1142 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Contentstack + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..1f44e34 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,27 @@ +## Security + +Contentstack takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations. + +If you believe you have found a security vulnerability in any Contentstack-owned repository, please report it to us as described below. + +## Reporting Security Issues + +**Please do not report security vulnerabilities through public GitHub issues.** + +Send email to [security@contentstack.com](mailto:security@contentstack.com). + +You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. + +Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: + +- Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) +- Full paths of source file(s) related to the manifestation of the issue +- The location of the affected source code (tag/branch/commit or direct URL) +- Any special configuration required to reproduce the issue +- Step-by-step instructions to reproduce the issue +- Proof-of-concept or exploit code (if possible) +- Impact of the issue, including how an attacker might exploit the issue + +This information will help us triage your report more quickly. + +[https://www.contentstack.com/trust/](https://www.contentstack.com/trust/) diff --git a/action.yml b/action.yml index 913efb2..d024632 100644 --- a/action.yml +++ b/action.yml @@ -52,8 +52,11 @@ inputs: outputs: fail_build: - description: 'true if any thresholds or SLAs were breached and action failed' + description: 'true if any thresholds or SLAs were breached for issues with available fixes' value: ${{ steps.snyk_analysis.outputs.fail_build }} + warn_build: + description: 'true if SLA breaches detected for issues without available fixes' + value: ${{ steps.snyk_analysis.outputs.warn_build }} runs: using: "composite" @@ -95,6 +98,7 @@ runs: const maxMedium = process.env.MAX_MEDIUM_ISSUES || '0'; const maxLow = process.env.MAX_LOW_ISSUES || '0'; const failBuild = process.env.fail_build || 'false'; + const warnBuild = process.env.warn_build || 'false'; // SLA breach counts const criticalSla = process.env.critical_sla_breaches || '0'; @@ -144,10 +148,17 @@ runs: comment += '| Severity | Breaches (with fixes) | Breaches (no fixes) | SLA Threshold (with/no fixes) | Status |\n'; comment += '|----------|----------------------|---------------------|------------------------------|--------|\n'; - const criticalSlaStatus = (parseInt(criticalSla) > 0 || parseInt(criticalSlaNoFix) > 0) ? '❌ Failed' : '✅ Passed'; - const highSlaStatus = (parseInt(highSla) > 0 || parseInt(highSlaNoFix) > 0) ? '❌ Failed' : '✅ Passed'; - const mediumSlaStatus = (parseInt(mediumSla) > 0 || parseInt(mediumSlaNoFix) > 0) ? '❌ Failed' : '✅ Passed'; - const lowSlaStatus = (parseInt(lowSla) > 0 || parseInt(lowSlaNoFix) > 0) ? '❌ Failed' : '✅ Passed'; + function slaStatus(withFix, noFix) { + const wf = parseInt(withFix), nf = parseInt(noFix); + if (wf > 0 && nf > 0) return '❌ Failed / ⚠️ Warning'; + if (wf > 0) return '❌ Failed'; + if (nf > 0) return '⚠️ Warning'; + return '✅ Passed'; + } + const criticalSlaStatus = slaStatus(criticalSla, criticalSlaNoFix); + const highSlaStatus = slaStatus(highSla, highSlaNoFix); + const mediumSlaStatus = slaStatus(mediumSla, mediumSlaNoFix); + const lowSlaStatus = slaStatus(lowSla, lowSlaNoFix); comment += `| 🔴 Critical | ${criticalSla} | ${criticalSlaNoFix} | ${slaCriticalWithFix} / ${slaCriticalNoFix} days | ${criticalSlaStatus} |\n`; comment += `| 🟠 High | ${highSla} | ${highSlaNoFix} | ${slaHighWithFix} / ${slaHighNoFix} days | ${highSlaStatus} |\n`; @@ -167,6 +178,9 @@ runs: if (failBuild === 'true') { comment += '❌ BUILD FAILED - Security checks failed\n\n'; comment += 'Please review and fix the security vulnerabilities before merging.\n'; + } else if (warnBuild === 'true') { + comment += '⚠️ BUILD PASSED WITH WARNINGS - SLA breaches detected for issues without available fixes\n\n'; + comment += 'Consider reviewing these vulnerabilities when fixes become available.\n'; } else { comment += '✅ BUILD PASSED - All security checks passed\n\n'; } diff --git a/snyk-parser.sh b/snyk-parser.sh index 21c4fca..31c176f 100755 --- a/snyk-parser.sh +++ b/snyk-parser.sh @@ -120,7 +120,9 @@ echo "SLA_LOW_NO_FIX=$SLA_LOW_NO_FIX" >> "$GITHUB_ENV" echo "Generating summary and checking thresholds..." fail_build=false +warn_build=false failure_reasons="" +warning_reasons="" if [ "$critical_count" -gt "$MAX_CRITICAL_ISSUES" ]; then fail_build=true @@ -139,25 +141,43 @@ if [ "$low_count" -gt "$MAX_LOW_ISSUES" ]; then failure_reasons="${failure_reasons}❌ LOW SEVERITY THRESHOLD BREACHED: Found $low_count low issues (max allowed: $MAX_LOW_ISSUES)\n" fi -if [ "$critical_sla_breaches" -gt 0 ] || [ "$critical_sla_breaches_no_fix" -gt 0 ]; then +if [ "$critical_sla_breaches" -gt 0 ]; then fail_build=true - failure_reasons="${failure_reasons}❌ CRITICAL SLA BREACHES: With fixes: $critical_sla_breaches, No fixes: $critical_sla_breaches_no_fix\n" + failure_reasons="${failure_reasons}❌ CRITICAL SLA BREACHES (with fixes): $critical_sla_breaches\n" fi -if [ "$high_sla_breaches" -gt 0 ] || [ "$high_sla_breaches_no_fix" -gt 0 ]; then +if [ "$critical_sla_breaches_no_fix" -gt 0 ]; then + warn_build=true + warning_reasons="${warning_reasons}⚠️ CRITICAL SLA BREACHES (no fixes): $critical_sla_breaches_no_fix\n" +fi +if [ "$high_sla_breaches" -gt 0 ]; then fail_build=true - failure_reasons="${failure_reasons}❌ HIGH SLA BREACHES: With fixes: $high_sla_breaches, No fixes: $high_sla_breaches_no_fix\n" + failure_reasons="${failure_reasons}❌ HIGH SLA BREACHES (with fixes): $high_sla_breaches\n" +fi +if [ "$high_sla_breaches_no_fix" -gt 0 ]; then + warn_build=true + warning_reasons="${warning_reasons}⚠️ HIGH SLA BREACHES (no fixes): $high_sla_breaches_no_fix\n" fi -if [ "$medium_sla_breaches" -gt 0 ] || [ "$medium_sla_breaches_no_fix" -gt 0 ]; then +if [ "$medium_sla_breaches" -gt 0 ]; then fail_build=true - failure_reasons="${failure_reasons}❌ MEDIUM SLA BREACHES: With fixes: $medium_sla_breaches, No fixes: $medium_sla_breaches_no_fix\n" + failure_reasons="${failure_reasons}❌ MEDIUM SLA BREACHES (with fixes): $medium_sla_breaches\n" +fi +if [ "$medium_sla_breaches_no_fix" -gt 0 ]; then + warn_build=true + warning_reasons="${warning_reasons}⚠️ MEDIUM SLA BREACHES (no fixes): $medium_sla_breaches_no_fix\n" fi -if [ "$low_sla_breaches" -gt 0 ] || [ "$low_sla_breaches_no_fix" -gt 0 ]; then +if [ "$low_sla_breaches" -gt 0 ]; then fail_build=true - failure_reasons="${failure_reasons}❌ LOW SLA BREACHES: With fixes: $low_sla_breaches, No fixes: $low_sla_breaches_no_fix\n" + failure_reasons="${failure_reasons}❌ LOW SLA BREACHES (with fixes): $low_sla_breaches\n" +fi +if [ "$low_sla_breaches_no_fix" -gt 0 ]; then + warn_build=true + warning_reasons="${warning_reasons}⚠️ LOW SLA BREACHES (no fixes): $low_sla_breaches_no_fix\n" fi echo "fail_build=$fail_build" >> "$GITHUB_OUTPUT" || true echo "fail_build=$fail_build" >> "$GITHUB_ENV" || true +echo "warn_build=$warn_build" >> "$GITHUB_OUTPUT" || true +echo "warn_build=$warn_build" >> "$GITHUB_ENV" || true # Write summary to the step summary file { @@ -201,26 +221,17 @@ echo "fail_build=$fail_build" >> "$GITHUB_ENV" || true echo echo "| Severity | Breaches (with fixes) | Breaches (no fixes) | SLA Threshold (with/no fixes) | Status |" echo "|----------|----------------------|---------------------|------------------------------|--------|" - if [ "$critical_sla_breaches" -gt 0 ] || [ "$critical_sla_breaches_no_fix" -gt 0 ]; then - echo "| 🔴 Critical | $critical_sla_breaches | $critical_sla_breaches_no_fix | $SLA_CRITICAL_WITH_FIX / $SLA_CRITICAL_NO_FIX days | ❌ Failed |" - else - echo "| 🔴 Critical | 0 | 0 | $SLA_CRITICAL_WITH_FIX / $SLA_CRITICAL_NO_FIX days | ✅ Passed |" - fi - if [ "$high_sla_breaches" -gt 0 ] || [ "$high_sla_breaches_no_fix" -gt 0 ]; then - echo "| 🟠 High | $high_sla_breaches | $high_sla_breaches_no_fix | $SLA_HIGH_WITH_FIX / $SLA_HIGH_NO_FIX days | ❌ Failed |" - else - echo "| 🟠 High | 0 | 0 | $SLA_HIGH_WITH_FIX / $SLA_HIGH_NO_FIX days | ✅ Passed |" - fi - if [ "$medium_sla_breaches" -gt 0 ] || [ "$medium_sla_breaches_no_fix" -gt 0 ]; then - echo "| 🟡 Medium | $medium_sla_breaches | $medium_sla_breaches_no_fix | $SLA_MEDIUM_WITH_FIX / $SLA_MEDIUM_NO_FIX days | ❌ Failed |" - else - echo "| 🟡 Medium | 0 | 0 | $SLA_MEDIUM_WITH_FIX / $SLA_MEDIUM_NO_FIX days | ✅ Passed |" - fi - if [ "$low_sla_breaches" -gt 0 ] || [ "$low_sla_breaches_no_fix" -gt 0 ]; then - echo "| 🔵 Low | $low_sla_breaches | $low_sla_breaches_no_fix | $SLA_LOW_WITH_FIX / $SLA_LOW_NO_FIX days | ❌ Failed |" - else - echo "| 🔵 Low | 0 | 0 | $SLA_LOW_WITH_FIX / $SLA_LOW_NO_FIX days | ✅ Passed |" - fi + sla_status() { + local with_fix=$1 no_fix=$2 + if [ "$with_fix" -gt 0 ] && [ "$no_fix" -gt 0 ]; then echo "❌ Failed / ⚠️ Warning" + elif [ "$with_fix" -gt 0 ]; then echo "❌ Failed" + elif [ "$no_fix" -gt 0 ]; then echo "⚠️ Warning" + else echo "✅ Passed"; fi + } + echo "| 🔴 Critical | $critical_sla_breaches | $critical_sla_breaches_no_fix | $SLA_CRITICAL_WITH_FIX / $SLA_CRITICAL_NO_FIX days | $(sla_status "$critical_sla_breaches" "$critical_sla_breaches_no_fix") |" + echo "| 🟠 High | $high_sla_breaches | $high_sla_breaches_no_fix | $SLA_HIGH_WITH_FIX / $SLA_HIGH_NO_FIX days | $(sla_status "$high_sla_breaches" "$high_sla_breaches_no_fix") |" + echo "| 🟡 Medium | $medium_sla_breaches | $medium_sla_breaches_no_fix | $SLA_MEDIUM_WITH_FIX / $SLA_MEDIUM_NO_FIX days | $(sla_status "$medium_sla_breaches" "$medium_sla_breaches_no_fix") |" + echo "| 🔵 Low | $low_sla_breaches | $low_sla_breaches_no_fix | $SLA_LOW_WITH_FIX / $SLA_LOW_NO_FIX days | $(sla_status "$low_sla_breaches" "$low_sla_breaches_no_fix") |" echo if [ "$critical_no_fix" -gt 0 ] || [ "$high_no_fix" -gt 0 ] || [ "$medium_no_fix" -gt 0 ] || [ "$low_no_fix" -gt 0 ]; then @@ -240,10 +251,21 @@ echo "fail_build=$fail_build" >> "$GITHUB_ENV" || true echo "❌ BUILD FAILED - Security checks failed" echo echo -e "$failure_reasons" - else + fi + if [ "$warn_build" = true ]; then + echo + echo "⚠️ WARNINGS - SLA breaches for issues without available fixes" + echo + echo -e "$warning_reasons" + fi + if [ "$fail_build" = false ] && [ "$warn_build" = false ]; then echo echo "✅ BUILD PASSED - All security checks passed" echo + elif [ "$fail_build" = false ] && [ "$warn_build" = true ]; then + echo + echo "⚠️ BUILD PASSED WITH WARNINGS" + echo fi } >> "$GITHUB_STEP_SUMMARY" 2>/dev/null || true