파워쉘 ps1 디지털 서명 오류는 PowerShell 실행 정책이 스크립트 파일에 신뢰할 수 있는 게시자의 서명을 요구하는데 실행하려는 ps1 스크립트에 해당 서명이 없기 때문에 나타납니다. 정확한 오류 메시지는 다음과 같습니다.
파일 xxx.ps1을(를) 로드할 수 없습니다. xxx.ps1 파일이 디지털 서명되지 않았습니다.
현재 시스템에서 이 스크립트를 실행할 수 없습니다.
File xxx.ps1 cannot be loaded. The file xxx.ps1 is not digitally signed.
You cannot run this script on the current system.
FullyQualifiedErrorId : UnauthorizedAccess
Windows는 브라우저·메신저·이메일 등 외부 출처에서 유입된 파일에 Mark of the Web(이하 MOTW) 표식을 자동으로 추가합니다. 파일 자체는 로컬에 있어도 “인터넷에서 온 파일”로 취급되게 만드는 내부 태그입니다.
Windows 클라이언트의 기본 실행 정책 Restricted는 서명 여부와 무관하게 모든 ps1 실행을 차단하고, Windows Server의 기본값 RemoteSigned는 MOTW가 추가된 파일에만 게시자 서명을 요구합니다.
로컬에서 직접 작성한 스크립트가 갑자기 차단됐다면, 해당 파일에 MOTW가 추가됐거나 그룹 정책이 AllSigned로 강제됐을 가능성이 높습니다.
단, 실행 정책은 사용자 작업을 물리적으로 막는 보안 시스템이 아니라 실수로 위험한 스크립트를 실행하지 않도록 하는 안전장치입니다. 그래서 관리자 권한 없이도 현재 세션에서만 실행 정책을 우회하는 방법이 존재합니다.
1. 파워쉘에서 ps1 디지털 서명 오류를 -ExecutionPolicy 인수로 무시하기
파워쉘 세션을 열 때 실행 정책 인수를 붙이면 해당 창에서 실행되는 스크립트만 서명 검증을 통과합니다. 시스템 전체 실행 정책을 바꾸지 않으므로 관리자 권한이 필요 없고, 창을 닫으면 원래 상태로 돌아가 가장 안전합니다.
PowerShell 7 이상에서는 실행 파일이 pwsh.exe로 바뀌었습니다. powershell.exe와 pwsh.exe 두 실행 파일은 동시에 설치될 수 있고 실행 정책도 버전별로 별도 관리되므로, 실행 중인 파워쉘 버전을 확인한 뒤 인수를 지정합니다.

# Windows PowerShell 5.1
powershell.exe -ExecutionPolicy Unrestricted -File "C:\Scripts\test.ps1"
# PowerShell 7.x
pwsh.exe -ExecutionPolicy Unrestricted -File "C:\Scripts\test.ps1"
-ExecutionPolicy Unrestricted는 서명되지 않은 스크립트 실행을 허용하는 옵션이고, -File은 실행할 ps1 경로를 지정합니다.
스크립트를 실행하지 않고 파워쉘 창만 우회 상태로 열려면 실행 창(Win + R)에서 powershell.exe -NoExit -ExecutionPolicy Unrestricted를 입력합니다. -NoExit은 명령 실행 후에도 창을 유지하는 옵션으로, 스크립트 결과를 확인하려는 경우에도 함께 지정합니다.
powershell.exe -NoExit -ExecutionPolicy Unrestricted -File "C:\Scripts\test.ps1"
마이크로소프트의 PowerShell 실행 정책 공식 문서는 Unrestricted를 “서명되지 않은 스크립트를 실행할 수 있으나 로컬 인트라넷 영역이 아닌 스크립트는 실행 전 사용자에게 경고한다”고 설명합니다. 프롬프트가 뜨면 R(한 번 실행) 또는 A(항상 실행)을 선택합니다.
경고 없이 완전히 차단을 해제하려면 Bypass를 사용합니다. Bypass는 서명 검증도 사용자 프롬프트도 요구하지 않으므로 자동화 스크립트나 CI 환경에서 주로 쓰입니다.
powershell.exe -ExecutionPolicy Bypass -File "C:\Scripts\test.ps1"
2. 인터넷에서 받은 파워쉘 파일을 차단 해제로 해결하기
실행 정책이 RemoteSigned인데도 로컬에 저장된 스크립트가 차단된다면, 해당 ps1 파일에 MOTW가 추가되었기 때문입니다.
Windows는 브라우저 다운로드, 메신저 첨부, 이메일 첨부, 네트워크 공유 폴더에서 복사한 파일에 대체 데이터 스트림(Alternate Data Stream)의 Zone.Identifier 값을 추가해 “인터넷에서 온 파일”로 표시하고, PowerShell은 이 MOTW를 확인해 해당 파일에 게시자의 디지털 서명을 요구합니다.

파일 하나만 해제하려면 탐색기에서 ps1 파일 우클릭 > 속성 > 일반 탭 하단의 보안 > 차단 해제 체크박스를 선택하고 확인을 누릅니다. 파일이 로컬 신뢰 영역으로 재분류되면서 RemoteSigned 정책에서도 실행이 허용됩니다.
차단 해제 항목이 보이지 않는 경우
파일 속성 창의 일반 탭에 “보안” 문구와 차단 해제 체크박스가 아예 나타나지 않는 경우가 있습니다.
GitHub, GitLab에서 받은 zip을 Windows 탐색기·PowerShell Expand-Archive·7-Zip 일부 버전으로 풀면 압축 해제 도구가 MOTW를 개별 파일에 전달하지 않아 항목이 표시되지 않고, FAT32·exFAT 볼륨에 저장된 파일도 파일 시스템이 ADS를 지원하지 않아 동일하게 나타나지 않습니다. 그룹 정책에서 첨부 파일의 MOTW 보존을 비활성화한 관리형 환경도 마찬가지입니다.
이 경우 MOTW의 실제 존재 여부를 명령으로 확인합니다.
Get-Item cmdlet에 -Stream Zone.Identifier 옵션을 붙여 파일의 ADS를 조회하면, MOTW가 있으면 스트림 정보가 출력되고 없으면 오류가 반환됩니다.
Get-Item "C:\Scripts\test.ps1" -Stream Zone.Identifier
MOTW가 있는 파일의 결과는 아래 형태로 스트림 정보와 길이가 출력됩니다.
PSPath : Microsoft.PowerShell.Core\FileSystem::C:\Scripts\test.ps1:Zone.Identifier
PSParentPath : Microsoft.PowerShell.Core\FileSystem::C:\Scripts
PSChildName : test.ps1:Zone.Identifier
PSDrive : C
PSProvider : Microsoft.PowerShell.Core\FileSystem
PSIsContainer : False
FileName : C:\Scripts\test.ps1
Stream : Zone.Identifier
Length : 26
MOTW가 없는 파일은 Could not open alternate data stream 'Zone.Identifier' of file 오류가 반환됩니다.
스트림이 존재하는데 속성 창에 차단 해제 항목이 안 뜨는 것은 GPO나 탐색기 감지 지연 문제이므로, Unblock-File cmdlet으로 강제 해제합니다.
스트림이 없는데도 실행 정책 오류가 뜬다면 MOTW가 아니라 실행 정책 자체가 Restricted나 AllSigned로 설정된 경우이므로 4번 항목의 Set-ExecutionPolicy 변경으로 처리합니다.
Unblock-File cmdlet 사용
파워쉘 명령으로 차단 해제를 처리하려면 Unblock-File cmdlet을 사용합니다. GUI 항목 유무와 무관하게 MOTW가 실제로 존재하면 제거하고, 없으면 아무 동작 없이 종료됩니다.
Unblock-File -Path "C:\Scripts\test.ps1"
폴더 하위의 모든 ps1 파일을 한 번에 해제하려면 파이프라인으로 재귀 처리합니다. GitHub에서 받은 저장소 zip을 풀어 여러 스크립트를 함께 실행하는 경우에 사용합니다.
Get-ChildItem -Path "C:\Scripts\" -Recurse -Filter *.ps1 | Unblock-File
파일 차단 해제 방법은 실행 정책을 변경하지 않으므로 시스템 보안 수준을 그대로 유지하면서 특정 파일만 신뢰하는 방식이 됩니다. RemoteSigned가 기본값인 Windows Server 환경에서 자주 쓰입니다.
3. 탐색기에서 ps1 파일 더블 클릭 실행을 위한 바로 가기와 관리자 권한 설정
ps1 파일을 탐색기나 바탕화면에서 더블 클릭하는 경우, 기본 동작은 스크립트 실행이 아니라 메모장 열기입니다.
Windows가 ps1 확장자를 편집기와 연결해 두었기 때문이고, ps1 파일의 기본 프로그램 연결을 PowerShell로 바꿔도 실행 정책 오류가 그대로 발생합니다. 파워쉘 창이 잠깐 열렸다가 오류 메시지와 함께 즉시 닫히기 때문에 원인 파악도 어렵습니다.
탐색기나 바탕화면 아이콘으로 스크립트를 실행하려는 상황에서는 ps1 파일을 직접 더블 클릭하지 말고, powershell.exe를 실행하는 바로 가기를 만들고 대상 인수에 ps1 파일 경로와 실행 정책 옵션을 함께 지정합니다.
바로 가기 하나만 만들면 이후 더블 클릭으로 서명 검증 없이 스크립트가 실행됩니다.
바로 가기 만들기

바탕화면에서 우클릭한 뒤 새로 만들기 > 바로 가기를 선택합니다. 항목 위치 입력란에 아래 형식으로 입력합니다.
powershell.exe -ExecutionPolicy Bypass -File "C:\Scripts\test.ps1"
-File 뒤에는 실행할 ps1의 전체 경로를 큰따옴표로 감쌉니다. 경로에 공백이 있어도 큰따옴표 안에 있으면 정상 인식됩니다. 다음을 눌러 바로 가기 이름 입력 단계로 넘어간 뒤, 원하는 이름을 지정하고 마침을 누르면 바탕화면에 바로 가기가 생성됩니다.
관리자 권한 실행 설정

레지스트리 수정, 서비스 제어, 시스템 폴더 접근이 포함된 스크립트라면 관리자 권한이 필요합니다.
생성한 바로 가기에서 우클릭 > 속성 > 바로 가기 탭 > 고급을 열고, 관리자 권한으로 실행 체크박스를 활성화한 뒤 확인을 누릅니다. 이후 더블 클릭할 때마다 UAC 프롬프트가 뜨고 승인 시 관리자 권한 파워쉘에서 스크립트가 실행됩니다.
스크립트 실행 후 결과 창을 유지하려면 대상 인수에 -NoExit을 추가해 아래 형태로 등록합니다.
powershell.exe -NoExit -ExecutionPolicy Bypass -File "C:\Scripts\test.ps1"
4. Set-ExecutionPolicy로 실행 정책 영구 적용하기
같은 시스템에서 ps1 스크립트를 반복적으로 실행한다면 실행 정책 자체를 영구 변경합니다. 실행 정책 인수를 매번 붙일 필요가 없어지고 파워쉘·터미널·VS Code 어디서 스크립트를 실행해도 변경한 실행 정책이 동일하게 적용됩니다.
정책 변경은 Set-ExecutionPolicy cmdlet으로 수행합니다. 기본 대상 범위는 LocalMachine이고 이 경우 관리자 권한 파워쉘이 필요합니다. 시작 메뉴에서 파워쉘을 우클릭해 관리자 권한으로 실행한 뒤 아래 명령을 입력합니다.
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned
변경 여부를 묻는 프롬프트가 뜨면 Y를 입력합니다. 이후 로컬에서 작성한 ps1은 서명 없이 실행되고, 인터넷에서 다운로드한 파일만 서명 또는 차단 해제가 필요한 상태가 됩니다. Windows Server와 동일한 기본값이므로 개발 환경에서 가장 균형 잡힌 설정입니다.
정책별 차이
| 정책 | 동작 |
|---|---|
| Restricted | 모든 스크립트 실행 차단. Windows 클라이언트 기본값 |
| AllSigned | 로컬·원격 모두 신뢰할 수 있는 게시자 서명 필요 |
| RemoteSigned | 로컬은 서명 불필요, 원격 파일만 서명 또는 차단 해제 필요 |
| Unrestricted | 서명 없이 실행 가능. 원격 파일은 실행 전 경고 |
| Bypass | 경고·프롬프트 없이 모두 실행. 자동화 환경용 |
| Undefined | 정책 미설정. 상위 범위 정책이 상속됨 |
관리자 권한이 없다면 실행 정책을 현재 사용자 범위로만 변경할 수 있습니다. -Scope CurrentUser를 붙이면 관리자 권한 없이 본인 계정에만 실행 정책을 적용합니다.
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
현재 정책 확인
변경 후 정책이 실제 반영됐는지 확인하려면 Get-ExecutionPolicy cmdlet에 -List 옵션을 붙여 모든 범위를 한 번에 조회합니다.
Get-ExecutionPolicy -List
결과는 아래 형태로 범위별 실행 정책이 출력됩니다.
Scope ExecutionPolicy
----- ---------------
MachinePolicy Undefined
UserPolicy Undefined
Process Undefined
CurrentUser RemoteSigned
LocalMachine AllSigned
여러 범위에 값이 지정된 경우 상위 범위가 우선하므로, 유효 실행 정책은 우선순위가 가장 높은 값으로 결정됩니다. 위 예시에서는 CurrentUser의 RemoteSigned가 유효하게 적용됩니다.
실행 정책 원상복구
변경한 실행 정책을 되돌리려면 Undefined로 설정합니다. Undefined는 정책 미설정 상태이므로 상위 범위 값이 상속되고, 모든 범위가 Undefined이면 Windows 클라이언트 기본값인 Restricted로 자동 복귀합니다.
Set-ExecutionPolicy -ExecutionPolicy Undefined -Scope CurrentUser
5. 정책을 바꿔도 오류가 계속 뜨는 원인
Set-ExecutionPolicy 명령을 성공적으로 실행했는데도 ps1 디지털 서명 오류가 계속 뜬다면, 상위 범위(Scope)의 실행 정책이 하위 범위의 실행 정책을 덮어쓰고 있기 때문입니다. PowerShell은 다음 우선순위로 유효 실행 정책을 결정합니다.
1. MachinePolicy (그룹 정책 - 컴퓨터)
2. UserPolicy (그룹 정책 - 사용자)
3. Process (현재 세션)
4. CurrentUser (현재 사용자)
5. LocalMachine (로컬 컴퓨터)
회사에서 지급받은 노트북처럼 그룹 정책이 강제된 환경에서는 MachinePolicy가 AllSigned 또는 Restricted로 잠겨 있어 Set-ExecutionPolicy가 아래 순위에 아무리 값을 넣어도 무시됩니다.
Get-ExecutionPolicy -List 결과에서 MachinePolicy나 UserPolicy 행에 값이 표시된다면 그룹 정책이 적용된 상태입니다.
이 경우 실행 정책 변경 대신 세션 단위 우회를 사용합니다. Process 범위는 그룹 정책보다 낮은 순위이므로 실행 정책 우선순위에 걸리지만, powershell.exe -ExecutionPolicy Bypass 형태로 시작 인수를 넘기면 해당 세션의 실행 정책이 별도 환경 변수 $Env:PSExecutionPolicyPreference로 설정돼 그룹 정책과 별도로 동작합니다.
세션 인수를 매번 붙이기 번거롭다면 바로 가기 대상 필드에 동일한 인수를 넣어 반복 실행 환경으로 만듭니다.
마치며
ps1 디지털 서명 오류는 스크립트 자체 문제가 아니라 PowerShell의 안전장치가 정상 작동하고 있다는 신호입니다.
로컬에서 방금 작성한 스크립트라면 실행 정책이 Restricted라서, 인터넷에서 받은 스크립트라면 파일에 원격 존 태그가 붙어 있어서 차단됩니다. 상황에 맞춰 세션 인수, 파일 차단 해제, 바로 가기 설정, 영구 정책 변경 네 가지 방법 중 하나를 선택하면 됩니다.
실행 정책을 영구 변경할 때는 RemoteSigned를 권장합니다. Windows Server 기본값과 동일하고, 로컬에서 작성한 스크립트는 자유롭게 실행하면서 인터넷에서 받은 파일에는 서명 확인이라는 최소한의 검증을 남기는 균형점입니다.
Bypass는 편리하지만 검증 자체를 없애는 옵션이므로 자동화 서버나 격리 환경이 아니면 세션 단위로만 사용합니다.
FAQ
Set-ExecutionPolicy가 “액세스 거부됨”으로 실패합니다.
기본 범위(LocalMachine)를 변경하려면 관리자 권한 파워쉘이 필요합니다. 시작 메뉴에서 파워쉘 아이콘을 우클릭한 뒤 관리자 권한으로 실행하거나, 관리자 권한이 없다면 -Scope CurrentUser를 붙여 현재 사용자 범위로 지정합니다.
Bypass와 Unrestricted의 차이는 무엇입니까?
Unrestricted는 인터넷에서 온 스크립트를 실행할 때 사용자에게 경고 프롬프트를 띄우고, Bypass는 어떤 경고도 없이 모두 실행합니다. 대화형 세션에서는 Unrestricted가 안전하고, 자동화 스크립트나 CI 파이프라인처럼 프롬프트에 응답할 수 없는 환경에서는 Bypass를 사용합니다.
ps1 스크립트에 직접 디지털 서명을 붙일 수 있나요?
New-SelfSignedCertificate cmdlet으로 인증서를 생성한 뒤 Set-AuthenticodeSignature cmdlet으로 스크립트에 서명을 추가할 수 있습니다. 자체 서명 인증서라도 신뢰할 수 있는 게시자 저장소에 등록하면 AllSigned 정책 환경에서도 실행이 허용됩니다. 다만 인증서 관리 부담이 크므로 개인 환경에서는 정책 변경이 더 실용적입니다.
Windows PowerShell 5.1에서 정책을 변경했는데 PowerShell 7에서 여전히 오류가 뜹니다.
powershell.exe(5.1)와 pwsh.exe(7.x)는 실행 정책을 별도로 관리합니다. PowerShell 7에서도 정책을 변경하려면 pwsh.exe를 관리자 권한으로 실행한 뒤 동일한 Set-ExecutionPolicy 명령을 다시 적용해야 합니다.



