Введение
Участник предлагает изменение кода с заголовком и описанием. Задание сборки превращает эти метаданные в предварительный артефакт. Непрерывная интеграция (CI) означает автоматический запуск таких заданий при поступлении изменений. Исполнитель — программа, выполняющая задание. Здесь вы сами запускаете предоставленный небольшой локальный исполнитель.
Все люди и события вымышлены. Исполнитель запускает настоящий Bash в одноразовом контейнере без сети и реквизитов развёртывания. production в release.conf — локальное тестовое значение, не вызывающее публикацию. Практикум моделирует подстановку текста и выполнение shell, а не триггеры или права облачного CI. CI Workshop — ваш терминал обслуживания; Topology объясняет поток и после обновления показывает реальные каналы запусков.
Вы выполните обычную сборку, проследите инъекцию в скрипт, измените два коротких файла и повторно проверите точность метаданных. Достаточно базового знакомства с терминалом; необходимый JSON и синтаксис Bash объясняются до использования.
Выполните обычную сборку
На этом шаге вы сначала увидите ожидаемый рабочий результат: точный заголовок участника становится артефактом, а канал остаётся preview.
Чтобы начать этот шаг, выберите вкладку CI Workshop в интерфейсе лабораторной работы.
Перейдите на вкладку CI Workshop. pwd выводит текущий каталог; ls перечисляет файлы. Рабочая область — /home/labex/project/ci-workshop.
Перед выполнением следующей команды перейдите на вкладку CI Workshop.
pwd
ls
cat показывает текстовый файл. Объект JSON заключает именованные поля в фигурные скобки; двоеточие связывает имя с значением. Строки используют двойные кавычки. Внутри строки \n обозначает перевод строки. Прочитайте обычное событие:
cat events/ordinary.json
Его title равен Improve search results. body — многострочное описание. Это данные участника, поэтому сборка не должна доверять им как командам.
Прочитайте небольшое определение задания и его скрипт:
cat job.json
cat build.sh
| Элемент | Значение в локальном исполнителе |
|---|---|
script |
Исполняемый файл Bash, сейчас build.sh |
env |
Сопоставление имён окружения со строками; сейчас пустое {} |
{{event.title}} |
Заменить этот точный шаблон заголовком до запуска Bash |
{{event.body}} |
Такая же подстановка описания |
artifact.txt |
Созданный сборкой файл метаданных |
release.conf |
Канал, инициализируемый как preview для каждого запуска |
Bash читает инструкции оболочки. TITLE="..." присваивает значение переменной; вокруг = пробелы запрещены. "$TITLE" раскрывает значение как один аргумент с сохранением пробелов и переводов строк. printf '%s' выводит строку без дополнительного перевода; одинарные кавычки сохраняют %s буквально. > перенаправляет вывод в файл, заменяя его содержимое. Точка с запятой разделяет команды. set -euo pipefail останавливает скрипт при типичных ошибках команд, неопределённых переменных и конвейеров, но не предотвращает инъекцию.
ci — команда подготовленного исполнителя. run принимает имя события без .json и новое имя выходного каталога. Каждый запуск начинает с новой конфигурации preview:
ci run ordinary first
Ожидаются channel=preview и exit=0. Ноль означает успешное завершение Bash. Посмотрите сгенерированный скрипт, артефакт и конфигурацию через show:
ci show first
Артефакт отображается как строка JSON, "Improve search results", чтобы далее можно было увидеть невидимые переводы строк. Это настоящее содержимое файла, а не имитация успешного результата. Последний раздел должен показывать preview. Перейдите на вкладку Topology и обновите страницу: её строка first читает тот же файл конфигурации.
Повторный run с именем first намеренно сообщает о существующем каталоге, сохраняя старые результаты. Выберите новое имя, например first-again. Неудачный запуск также сохраняет сгенерированный скрипт и build.log в runs/NAME для диагностики.
Проследите опасную подстановку
На этом шаге вы увидите превращение данных в исполняемый код и изменение канала внутри изолированного демонстрационного запуска.
Чтобы начать этот шаг, выберите вкладку CI Workshop в интерфейсе лабораторной работы.
Поток: событие → задание → сгенерированный shell-код → Bash → артефакт. Опасна подстановка до разбора кавычек Bash. Двойные кавычки защищают раскрытие переменной в уже разобранной команде, но не исходное значение, вставленное в код до разбора.
Прочитайте предоставленное безвредное демонстрационное событие:
Перед выполнением следующей команды перейдите на вкладку CI Workshop.
cat events/hostile.json
title содержит двойную кавычку, точку с запятой, printf, ещё одну точку с запятой и #. В Bash кавычка завершает исходную строку, точка с запятой начинает новую команду, а # комментирует остаток строки. Этот printf меняет только синтетическую release.conf данного запуска. \" в JSON кодирует кавычку, но не делает её безопасной при последующей вставке в shell-код.
Запустите событие в новом рабочем каталоге:
ci run hostile demo
ci show demo
Ожидайте channel=production, хотя исполнитель начал с preview. В generated.sh найдите вставленный printf между точками с запятой: Bash действительно выполнил его. Артефакт может содержать лишь Update, потому что остальной текст стал синтаксисом вместо заголовка. Это и нужно исправить.
Каталог demo отделён от first; ни один запуск не изменяет job.json или build.sh. Перейдите на вкладку Topology и обновите страницу, чтобы сравнить фактические каналы. Строка production означает изменённые учебные данные, а не настоящий релиз. Не выполняйте текст события вручную в своей оболочке обслуживания.

Общий риск описан в документации GitHub об инъекциях в скрипты. Наши шаблоны и формат задания намеренно меньше GitHub Actions; общий механизм — подстановка перед разбором.
Передайте значение как данные
На этом шаге вы исключите текст участника из исходного shell-кода, сохранив пробелы, кавычки и несколько строк.
Чтобы начать этот шаг, выберите вкладку CI Workshop в интерфейсе лабораторной работы.
Переменная окружения — именованная строка, передаваемая новому процессу. Сопоставление env задаёт её напрямую, не создавая shell-присваивание. В JSON это ещё один объект в фигурных скобках. Задайте BUILD_TITLE из {{event.title}}, а Bash пусть раскрывает "$BUILD_TITLE" во время выполнения. Кавычки, точки с запятой, $() и обратные кавычки внутри раскрытого значения не интерпретируются как новые команды. Не применяйте eval и не передавайте значение в bash -c: они разберут его снова.
Заменим два файла с помощью here-document. cat > filename <<'JSON' записывает следующие строки до строки, содержащей только JSON. Кавычки вокруг ограничителя запрещают оболочке обслуживания раскрывать $ и другой синтаксис. Копируйте блок целиком, включая завершающий ограничитель. Он заменяет весь файл, поэтому помогает восстановиться после опечаток.
Перед выполнением следующей команды перейдите на вкладку CI Workshop.
cat > job.json <<'JSON'
{
"script": "build.sh",
"env": {
"BUILD_TITLE": "{{event.title}}"
}
}
JSON
Теперь замените скрипт. Ограничитель BASH имеет тот же смысл буквальной записи. Скрипт напрямую использует окружение и больше не содержит шаблон участника.
cat > build.sh <<'BASH'
set -euo pipefail
printf '%s' "$BUILD_TITLE" > artifact.txt
printf 'channel='; cat release.conf
BASH
Перечитайте оба файла знакомой командой cat. Пропущенная запятая или скобка вызывает ошибку JSON; неверное имя окружения — ошибку неопределённой переменной. Полностью повторите нужный блок и попробуйте снова. Старый запуск относится к старому скрипту, поэтому выберите новое имя:
ci run ordinary repaired
ci show repaired
Сгенерированный код теперь содержит "$BUILD_TITLE", а не символы заголовка. Артефакт по-прежнему содержит Improve search results, канал — preview.
Перед проверкой прочитайте примеры пунктуации и нескольких строк:
cat events/quotes.json
cat events/multiline.json
\n в JSON означает реальный перевод строки; последний \n тоже должен сохраниться. Апостроф в O'Brien и двойные кавычки в заголовке — допустимые данные. Тем же способом передаётся многострочный body: ссылка меняется на {{event.body}}, правило кавычек вокруг переменной остаётся прежним. Это пригодится в испытании с примечаниями к выпуску.
ci test normal выполняет неизменённые отправленные задание и скрипт с обычными, пунктуационными и многострочными событиями в одноразовых временных каталогах. Он сравнивает точные байты и проверяет preview. Удаляются только эти каталоги; отправленные файлы и сохранённые запуски остаются неизменными.
ci test normal
Для каждого примера ожидается exact metadata; channel=preview. Удаление пунктуации, склеивание строк, фиксированный заголовок, отказ всем событиям или пропуск сборки провалят проверку полезной функции. Ошибка называет пример: прочитайте его и исправьте два файла перед повтором.
Повторно проверьте границу сборки
На этом шаге вы подтвердите, что исправленное задание сохраняет обычные метаданные и предотвращает показанный побочный эффект.
Чтобы начать этот шаг, выберите вкладку CI Workshop в интерфейсе лабораторной работы.
Повторите вредоносный пример с новым именем вывода:
Перед выполнением следующей команды перейдите на вкладку CI Workshop.
ci run hostile repaired-hostile
ci show repaired-hostile
Теперь артефакт должен содержать весь вредоносный заголовок как текст. В JSON-представлении видны точки с запятой и кавычки, а release.conf остаётся preview. Старые результаты demo не меняются: это другой рабочий каталог.
Другой пример содержит $() и обратные кавычки — формы подстановки команд, если они записаны в shell-коде. В раскрытом значении окружения в двойных кавычках эти символы остаются данными. Прочитайте пример:
cat events/substitution.json
Проверьте все пять примеров с теми же отправленными файлами:
ci test all
ordinary, quotes, multiline, hostile и substitution должны сохранить точные метаданные и preview, после чего появится сообщение об очистке. Проверяются реальное выполнение Bash и выходные файлы, а не фраза журнала или выдуманное secure=true. Проверка завершения повторяет временные тесты без изменений задания, скрипта и сохранённых запусков.
Если сбой остаётся только во враждебном случае, проверьте, остались ли в файле оболочки шаблоны событий или повторный разбор переменной. Если не проходят пунктуация или многострочный текст, проверьте printf '%s' с переменной в двойных кавычках. Не удаляйте проблемные входные данные: корректная обработка законных метаданных — часть результата. Перейдите на вкладку Topology и обновите страницу, чтобы увидеть исправленный враждебный запуск рядом с прежней демонстрацией.

Резюме
Вы проследили метаданные участника через локальный исполнитель до настоящего Bash, воспроизвели изолированную подмену конфигурации и исправили границу данных сопоставлением окружения и раскрытием в кавычках. Точные проверки сохранили пунктуацию, многострочный текст и предварительный канал. Далее примените тот же подход к примечаниям выпуска.



