Robert.agent in action

Here’s an example of how clever AI is getting.

Someone sent the following screen shot of PowerShell code to robert.agent@ciaops365.com. Which, if you haven’t seen, is an agent I built to respond automatically to emails using Copilot Studio.

Screenshot 2025-07-10 130705

My Copilot Agent was able to read the PowerShell inside the screen shot and return the following 103 lines of PowerShell for that person!

Screenshot 2025-07-10 130823

Why don’t you give robert.agent@ciaops365.com a try to get your Microsoft Cloud questions answered?

How I 13x’d my code with AI

bp1

A long time ago I manually cobbled together a PowerShell script to update the M365 required PowerShell modules on a Windows device. You can find that now ‘ancient’ version here:

https://github.com/directorcia/Office365/blob/30c6d020f48a7c8ed8ff7abeb64f4e30803d7c4b/o365-update.ps1

It worked well but it was growing stale and needed and refresh and update. Having been working with Github Copilot’s agent capabilities on new scripts like:

https://blog.ciaops.com/2025/05/27/powershell-script-for-analyzing-exchange-online-email-headers/

I decided it was perhaps time to make seismic shift in how I thought about the code I write thanks to AI.

Being a trained engineer, to me code is simply a tool that I can use to make my job easier and quicker. In short, I understand code but I am not a developer. This allows me to use languages like PowerShell to create automations. However, these attempts have never been ideal in my books and always suffer from limitations, especially when it comes to error handling. Also, I know enough about PowerShell to get by, but I also know there is a hell of a lot more it can do. However, I knew I would never get the time to get to any mastery level.

Then along came AI. Now I was able to create the scripts that I wanted in a much shorter time and utilising far more of the full capabilities available in PowerShell. This made me realise that, thanks to AI, I have moved up the ladder from an unskilled PowerShell ‘hack’ to more of a software architect/engineer with an very capable programming employee being AI. Now, I don’t need to write every line of code as I did with my original module update script, all I needed to do is now tell my new digital coding employee what needs to be done and monitor the result

So, starting with the original 200 lines of code I asked Github Copilot to ‘improve’ the script. This started a journey of almost 2 full days of getting to a script of around 2400 lines but with far more functionality. Best of all, I didn’t write a single line of additional code, my AI coding employee did it for me.

That journey also taught me some important lessons about what is now termed ‘vibe’ coding. You can’t simply expect AI to get it right the first time. It took me many iterations and prompting to get what I wanted and fix the many, many errors that manifested along the way. Perhaps the most interesting was when the AI just didn’t seem to fix an error that manifested itself with constrained mode PowerShell. The lesson I learned is that I had to dig in a bit and help the AI focus on the parts of the code where the problem was. Without doing that it seemed to only take a high level view of the code, overlooking the obscure error. Thus, I still needed my PowerShell and ‘engineering’ skills to direct my AI employee to the solution.

It dawned on me that I needed to do more than just be a ‘manager’ and sit back and give commands (prompts) and expect a perfect output every time. in fact, I needed to be an ‘architect’ and get more involved and help my AI employee solve the problem, just like you would any junior or entry level resource. Only then, did I really start making headway of solving problems as they arose and drive to the 2400 lines of coded solution that is available to you today for free.

Github Copilot and I have continue to refine the code to the point now were it does so many things I simply could not have done myself without investing probably thousands of hours into. Yes, I ‘could’ have but I have now learned ‘why’ would i? Creating a 2400 line free script on my own is simply not an economically viable investment of my time. Thanks to AI, I have been able to achieve the same, if not better result, in a much, much shorter time frame.

I can now take my new found knowledge of using AI to code and position myself as an ‘architect’ to solve many of the automation challenges I have wanted to solve with PowerShell. By removing the need to code and debug every line of code I achieve a far more effective and efficient result, without the need of involving anyone else but me. I remember hearing the saying that ‘your job won’t be replaced by AI alone, but it will be replaced by someone using AI’ and to me, my recent experience confirms exactly that.

If you have managed to get this far, the the good news is that my revamped o365-update.ps1 script has now been improved to include such features as:

– removal of depreciated modules

– removal of previous module versions

– supports multi-threading

– supports constrained language mode

– and more.

The documentation which is here:

https://github.com/directorcia/Office365/wiki/Update-all-Microsoft-Cloud-PowerShell-modules

which was also totally Ai generated! And of the course the code is at:

https://github.com/directorcia/Office365/blob/master/o365-update.ps1

The leverage that Github Copilot has already provided me and what I now envision it will allow me to, I could of only dreamed of as a single person ‘hack’ only a short time ago! My AI employee and I are now off to solve the next challenge. Stay tuned.

PowerShell script for analyzing Exchange Online email headers

Source = 

https://github.com/directorcia/Office365/blob/master/email-header-report.ps1

Overview

The Email Header Report Tool is a PowerShell script that analyzes email headers to identify potential spam, phishing, and security concerns in messages processed by Exchange Online and Microsoft 365. This tool provides security administrators and email analysts with a comprehensive report of authentication results, spam filtering decisions, and other security-related information embedded in email headers.

Features

    • Authentication Analysis: Evaluates SPF, DKIM, and DMARC authentication results
    • Spam Filter Analysis: Examines SCL (Spam Confidence Level) and other spam indicators
    • Defender for Office 365 Analysis: Analyzes Safe Links and Safe Attachments processing results
    • Transport Rule Detection: Identifies if mail flow rules were applied to the message
    • Risk Assessment: Provides an overall verdict with color-coded risk indicators
    • Recommendations: Suggests appropriate actions based on analysis results

Requirements

    • PowerShell 5.0 or higher
    • Access to email headers from Exchange Online/Microsoft 365 environment
    • Windows with support for color console output (for optimal viewing experience)

Usage

.\email-header-report.ps1 -HeaderFilePath "C:\path\to\email_header.txt"

Parameters

Parameter Type Required Description
HeaderFilePath String Yes Path to the text file containing the raw email header

How to Extract Email Headers

From Outlook Desktop

    1. Open the email message
    2. Click File > Properties
    3. The headers appear in the “Internet headers” box
    4. Select all and copy to a text file

From Outlook Web App (OWA)

    1. Open the email message
    2. Click the three dots (⋯) in the top-right corner
    3. Select “View message details” or “View > Message details”
    4. Copy the headers to a text file

From Microsoft 365 Security Portal

    1. Navigate to the message in quarantine or Explorer view
    2. Select the message and view details
    3. Find and copy the headers to a text file

Understanding the Report

The report is divided into several sections:

Authentication Analysis

Shows the results of email authentication protocols:

    • SPF (Sender Policy Framework): Verifies if the sending server is authorized to send email for the domain
    • DKIM (DomainKeys Identified Mail): Validates the digital signature attached to the message
    • DMARC (Domain-based Message Authentication, Reporting, and Conformance): Evaluates alignment between the sender’s domain and the authenticated domain
    • CompAuth: Microsoft’s composite authentication result

Spam Filtering Analysis

Details how Exchange Online Protection and Microsoft 365 evaluated the message:

    • SCL (Spam Confidence Level): Score from -1 to 9 indicating spam probability
    • BCL (Bulk Complaint Level): Score from 0 to 9 for bulk email
    • Forefront Anti-Spam Report: Detailed anti-spam processing information
    • Delivery Destination: Where the message was delivered (Inbox, Junk, Quarantine, etc.)

Safe Attachments Analysis

Shows results from Defender for Office 365 attachment scanning:

    • CLEAN: No malicious content detected
    • BLOCK: Malicious content detected and blocked
    • REPLACE: Malicious attachment replaced with a placeholder
    • DYNAMICDELIVERY: Attachment analysis performed with temporary placeholder

Safe Links Analysis

Shows results from Defender for Office 365 URL scanning:

    • CLEAN: No malicious URLs detected
    • BLOCK: Malicious URLs detected and rewritten/blocked
    • PENDING: Analysis in progress
    • NOT SCANNED: URLs were not evaluated

General Message Analysis

Provides additional information about the message:

    • Originating IP: Source IP address of the sender
    • Message ID: Unique identifier for the message
    • Return-Path vs From: Compares the envelope sender with the display sender

Analysis Summary

Provides an overall verdict based on all factors:

    • HIGH RISK / SPAM DETECTED: Strong indicators of being spam or malicious
    • POTENTIAL RISK / LIKELY SPAM: Several characteristics of spam or unwanted mail
    • LIKELY LEGITIMATE: Message appears to be legitimate based on key checks
    • MIXED RESULTS / CAUTION ADVISED: Some checks passed, others raised concerns

Interpreting Key Values

SCL (Spam Confidence Level)

Value Meaning Typical Action
-1 Trusted sender Bypasses spam filtering
0-1 Not spam Delivered to inbox
2-4 Low spam probability Usually delivered to inbox
5-6 Spam Usually delivered to junk folder
7-9 High confidence spam Quarantined or rejected

Authentication Results

Result Meaning
Pass Authentication successful
Fail Authentication failed
SoftFail Weak failure (typically for SPF)
Neutral No policy assertion
None No policy found
PermError Permanent error in policy
TempError Temporary error during lookup

Examples

Legitimate Message Example

AUTHENTICATION ANALYSIS
-----------------------
  [SPF] PASS
  [DKIM] PASS
  [DMARC] PASS
  [Composite Auth (CompAuth)] PASS

EXCHANGE ONLINE SPAM FILTERING ANALYSIS
--------------------------------------
  [SCL (Spam Confidence Level)] 0 - Not spam (message determined to be clean by EOP content filter).
  
MESSAGE VERDICT:
──────────────────────────────────────────────────
  ✅ LIKELY LEGITIMATE
     This message appears to be legitimate based on key checks.
            

Spam Message Example

AUTHENTICATION ANALYSIS
-----------------------
  [SPF] FAIL
  [DKIM] FAIL
  [DMARC] FAIL
  [Composite Auth (CompAuth)] FAIL

EXCHANGE ONLINE SPAM FILTERING ANALYSIS
--------------------------------------
  [SCL (Spam Confidence Level)] 9 - Definite spam (highest confidence, typically quarantined or rejected).
  
MESSAGE VERDICT:
──────────────────────────────────────────────────
   HIGH RISK / SPAM DETECTED
     This message shows strong indicators of being spam or malicious.
            

Troubleshooting

Script Errors

    • Ensure you’re using PowerShell 5.0 or higher
    • Verify the header file exists and is readable
    • Check that the header file contains valid email headers

Missing Information

Some headers might not be present depending on:

    • Email routing path
    • Microsoft 365 subscription level
    • Security features enabled in your tenant
    • Age of the message (older messages might use different headers)

False Positives/Negatives

    • The tool analyzes only what’s present in the headers
    • It doesn’t re-evaluate the message content
    • Discrepancies may occur if policies changed after message delivery

Advanced Usage

Piping Output

You can redirect the output to a file:

.\email-header-report.ps1 -HeaderFilePath "C:\path\to\header.txt" > "report.txt"

Incorporating into Other Scripts

The script can be called from other PowerShell scripts or functions:

& "C:\path\to\email-header-report.ps1" -HeaderFilePath $headerPath

References

License

This script is provided as-is with no warranties. Use at your own risk.

Documentation for Email Header Report Tool v1.1

Author: CIAOPS

For updates and more information: GitHub Wiki

PowerShell script to report EntraID signin update

One the things that I have tasked myself with is to go back through my scripts and using AI (aka Github Copilot) to improve my code.

Screenshot 2025-04-18 095201

The latest script to get this treatment is:

https://github.com/directorcia/Office365/blob/master/graph-signins-get.ps1

which now has greater flexibility and speed. I also used Copilot to produce documentation for the script which is here:

https://github.com/directorcia/Office365/wiki/Get-tenant-signins

In my Visual Studio Code editor what I did was simply to open up the script.

Screenshot 2025-04-18 100356

I then set Copilot to operate in ‘agent’ mode, as shown above. I also selected an AI model to use. I have the default choices of:

Screenshot 2025-04-18 100555

I can also configure others like Gemini if I want. This time I selected Claude 3.7 and then basically told Copilot to ‘improve’ my code. After that I asked it to provide options for using paging to get more results as well as ensuring the output was in local time.

After one update to the time format it produced an error when it ran but I simply told Copilot to fix that error and it did so. The code once again executed.

Thus, the updated script and documentation is now available via the links above and I am amazed at how easy it was to make all these changes to get the result that I wanted without having to type any additional code myself into the script! I suppose he downside is that the code is more complex and I don’t intrinsically understand it as well as if I had written every line, but I have Copilot to help explain any part of the code to me if needed and the time savings getting to a result speak for themselves.

The functionality that AI provided for me via Github Copilot is enormous and should make short work of any PowerShell automation I do in the future. If you are using PowerShell (or any code) then you really need to be looking at the benefits AI will provide you.

Script to delete old installed PowerShell module versions

image

A while ago I wrote a script that report all the previous versions of PowerShell modules that have been installed.

https://blog.ciaops.com/2025/03/28/report-installed-powershell-module-versions/

I’ve now done a script that will allow yoru to delete all these previous versions while retaining the current version. You’ll find that script here:

https://github.com/directorcia/Office365/blob/master/psmodules-del.ps1

# Example usage:
# Remove-OldPSModules                                                  # Process all modules without confirmation
# Remove-OldPSModules -SummaryOnly                                     # Only show summary info, minimize verbose output
# Remove-OldPSModules -ModuleNames “Microsoft.Graph”, “Az”            # Process specific modules
# Remove-OldPSModules -ConfirmUninstall                               # Ask before each removal
# Remove-OldPSModules -WhatIf                                         # Simulation mode, no actual changes
# Remove-OldPSModules -ModuleNames “Az” -ConfirmUninstall -WhatIf     # Combine parameters as needed

You can modify the execution part of the script at the bottom to suit your needs.

Updated Defender for Endpoint Security Baseline

image

Microsoft has updated the Defender for Endpoint Security Baseline policy in Intune to Version 24H1 as shown above.

I have managed to extract my own best practice JSON configuration file for this policy and make it available at:

https://github.com/directorcia/bp/blob/main/Intune/Policies/Endpoint/Baselines/dep.json

which means you can import this directly into your environment programmatically (I used PowerShell to do exactly this).

The updates to this policy are huge! The previous version config file was about 350 lines, this new 24H1 version is now about 2,300 lines long! This indicated to me that Microsoft is moving more and more settings into theses baselines.